package com.cilico.utils;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.zip.GZIPOutputStream;

import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Shader.TileMode;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Environment;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.RelativeLayout;

import com.cilico.ConfigManager;
import com.cilico.Mid;
import com.cilico.R;
import com.cilico.R.drawable;
import com.cilico.components.AtomParser;
import com.cilico.components.Component;
import com.cilico.components.Component.SelfLayout;
import com.cilico.components.CssStyle;
import com.cilico.components.Div;
import com.cilico.components.ImageItem;
import com.cilico.components.Label;
import com.cilico.components.Radio;
import com.cilico.components.RowPanel;
import com.cilico.components.Select;
import com.cilico.components.TabItem;
import com.cilico.components.Table;
import com.cilico.components.WaitDialog;
import com.cilico.components.Wrap;
import com.cilico.components.cCheckBox;
import com.cilico.components.mButton;
import com.cilico.components.mHtmlText;
import com.cilico.components.mTextField;
import com.cilico.view.BaseView;
import com.cilico.view.FormAction;
import com.cilico.view.FormLayout;
import com.cilico.view.LPLinearLayoutView;
import com.cilico.view.LoginView;
import com.cilico.view.SegmentLinearLayout;
import com.cilico.waterfall.ItemBase;
import com.cilico.waterfall.ItemInfo;
import com.cilico.waterfall.ItemMeal;
import com.cilico.waterfall.ItemRestaurant;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;


////#define DEBUG

/**
 * 工具类
 */
public final class Utils {
	public static String wapHost = "http://10.0.0.172:80";
	private static Select needsettleComponetsAgainSelect = null;
    static final int OK_KEY = -5;
    static final int LEFT_SOFTKEY = -6;
    static final int RIGHT_SOFTKEY = -7;
    public static final int NUM_THREADS = 3;

    //用于减少快速点击手机返回键导致程序强制关闭的问题
    public static boolean isbackcompleted_ = true;
    //是否隐藏titleBar
    public static boolean hiddenTitleBar_ = false;
    /**
     * Used as indices in text parser's return result of a line break in a string.
     */
    public static final int LBI_BREAK = 0; // Break position (this char is in current
    // line)
    public static final int LBI_NEXT = 1; // Next char position to resume scanning (to
    // skip tags)
    public static final int LBI_TYPE = 2; // Line break type: newline, paragraph, ...,
    // defined below.
    public static final int LBI_START = 3; // Starting position of this line.
    public static final int LBI_SIZE = 4; // Number of linebreak indices.

    /**
     * Types of line breaks.
     */
    public static final int LB_NEWLINE = 0;
    public static final int LB_PARAGRAPH = 1;
    public static final int LB_SKIP = 2; // Skip characters within [LBI_BREAK, LBI_NEXT)
    public static final int LB_HYPHEN = 3;

    /**
     * Used for gzip. Re. rfc1951.
     */
    public static int gIndex = 0;
    public static int bitByte = 0;
    public static int bitIndex = 0;
    private static final int MAX_BITS = 16;
    private static final int[] EXTRA_L_BITS = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
            5, 5, 5, 5, 0 };
    private static final int[] EXTRA_L_VALUES = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51,
            59, 67, 83, 99, 115, 131, 163, 195, 227, 258 };
    private static final int[] EXTRA_D_BITS = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
            10, 11, 11, 12, 12, 13, 13 };
    private static final int[] EXTRA_D_VALUES = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
            513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 };
    private static final int[] DYNAMIC_L_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };

    private static byte[] lock_ = new byte[0]; 
    public static int screenWidth_ = 0;
    public static int screenHeight_ = 0;

	
    /**
     * The number of alpha transparency levels。will be reset by numAlphaLevels() in LPMid.java. The minimum
     * numAlphaLevel_ is 2, which indicates only support for full transparency and full opacity.
     */
    static int numAlphaLevel_ = 256;

    public final static int BLUE = 0xFF0000FF;
    public final static int WHITE = 0xFFFFFFFF;
    public final static int BLACK = 0xFF000000;
    public final static int GREY = 0xFF808080;
    public static int SELECTED_LINK_COLOR = 0xFF808080;
    public final static int TABBARBACKGROUNDCOLOR = 0xFF294B78;

    public final static char MATCH = '\"';

    /** True if the user selects item Map */
    static boolean toMapView_;

    /**
     * Progress indictor image.
     */
    public static Bitmap progress_;

    public static final String SPLIT_CHARACTERS = " ,.";

    // 界面参考缩放参数
    public static float SCALEDATE_W;
    public static float SCALEDATE_H;
    public static float DM_DENSITY;
    // 图片缓存
    public static Bitmap bitmap_;
    public static boolean userIsNotFirstLogin_ = true;

    // 解读并存储assets文件夹下的Config.txt文件信息
    private static HashMap<String, String> configHm_;
    // 连续点击事件的时间间隔限制
    public static int jat_lag = 0;
    
    // 获取系统版本号
    public static float getSystemVersion() {
        String systemVersio = android.os.Build.VERSION.RELEASE;
        int index = systemVersio.indexOf('.');
        if (index > 0) {
            systemVersio = systemVersio.substring(index - 1, index + 2);
        }
        Utils.printOutToConsole("systemVersion === " + systemVersio);
        float systemVersion = 0;
        try {
            systemVersion = Float.parseFloat(systemVersio);
        } catch (Exception e) {
            Utils.printException(e);
            systemVersion = (float) 1.6;
        }
        return systemVersion;
    }

    /**
     * 从资源图片里面获取指定文件名的图片，如果没有就返回空
     * 
     * @param 指定的要查找的文件名
     * @param 界面对象
     * @return
     */
    public static Bitmap getBitmapFromDrawable(String bitmapName, BaseView bv) {
        // 利用反射机制获取对象域名
        Object obj = null;
        String varName = null;
        Field[] fields = R.drawable.class.getDeclaredFields();
        int size = fields.length;
        for (int i = 0, len = size; i < len; i++) {
            // 对于每个属性，获取属性名
            varName = fields[i].getName();
            if (varName.equals(bitmapName)) {
                try {
                    // 获取原来的访问控制权限
                    boolean accessFlag = fields[i].isAccessible();
                    // 修改访问控制权限
                    fields[i].setAccessible(true);
                    // 获取在对象f中属性fields[i]对应的对象中的变量
                    obj = fields[i].get(varName);
                    // 恢复访问控制权限
                    fields[i].setAccessible(accessFlag);
                    int id = Integer.parseInt(obj.toString());
                    Bitmap bm = ConstantRepository.decodeBitmap(bv.getResources(), id);
                    return bm;
                } catch (IllegalArgumentException ex) {
                    Utils.printException(ex);
                } catch (IllegalAccessException ex) {
                    Utils.printException(ex);
                }
            }
        }
        return null;
    }

    /**
     * parser html
     */
    public static void parseUsingkXML(String xml, BaseView activity) {
        if (xml == null || xml.trim().equals(""))
            return;
        String text = xml;
        try {
            xml = Utils.unescapeHTML(text);
        } catch (Exception ex) {
            xml = text;
        }
        try {
        	xml = "<body>" + xml + "</body>";
            xml = new String(xml.getBytes("UTF-8"));
			xml = Utils.insteadOfSpecillCharacter(xml, true); // 将字符串中包含的特殊字符进行转化
			 // 此句打印可以直接找到xml报文中不符合解析器规范的非法字符，后面截取子字符串的下标根据解析器抛的异常点来决定
			 if (xml.length() > 19673) {
			 printOutToConsole("not well-formed (invalid token) = " + xml.substring(19600, 19675));
			 }
			if (null == BaseView.mid_.parser_)
				BaseView.mid_.parser_ = new AtomParser(BaseView.mid_);
			if (!BaseView.mid_.waitDialog_.getDisplayTaskStatus()) {
				synchronized (lock_) {
					BaseView.mid_.parser_.setkXMLItemsProperty(AtomParser.parsekXMLItems_, activity);
					android.util.Xml.parse(xml, BaseView.mid_.parser_);
				}
			}
			if (xml.contains("很抱歉，会话超时，请重新登录或退出")) {
				BaseView.istimeout_ = true;
			}
        } catch (Exception e) {
            Utils.printException(e);
        }
    }
    

    // 计算界面宽高
    public static void calculateScreenSize(Activity activity) {
        DisplayMetrics dm = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        screenWidth_ = dm.widthPixels;
        screenHeight_ = dm.heightPixels;
        setScaledParams(screenWidth_, screenHeight_, dm.scaledDensity);
    }

    /**
     * 由于ophone1.6以下的系统无法支持<supports-screens android:smallScreens="true" android:normalScreens="true"
     * android:largeScreens="true" android:anyDensity="false"> </supports-screens>属性设置，但是会出现大屏幕界面布局局限的情况
     * 该方法针对此种情况对界面数据进行相应的缩放，参照的比例是320X480
     * 
     * @param screenWidth
     *            参照宽度
     */
    private static void setScaledParams(float screenWidth, float screenHeight, float density) {
        // TODO Auto-generated method stub
        final float origWidth = 320;
        //final float origHeight = 480;
        if (screenWidth > origWidth) {
            SCALEDATE_W = screenWidth / (origWidth * density);
            SCALEDATE_H = SCALEDATE_W;
            DM_DENSITY = density;
		} else {
			SCALEDATE_W = 1;
			SCALEDATE_H = 1;
			DM_DENSITY = 1;
		}
    }

    /** 
     * 设置控件联动关系的公共部分
     * @param bv
     * @param isWorked
     * @param relaEnable
     * @param relaDisable
     * @param relaVisible
     * @param relaInvisible
     * @param component
     */
    public static void settleComponetsChild(BaseView bv, boolean isWorked, String[] relaEnable, String[] relaDisable, String[] relaVisible, String[] relaInvisible, Component component) {
        String nameFormTemp = "";
        if (null == relaEnable && null == relaDisable && null == relaVisible && null == relaInvisible) {
            return;
        }
        View view = null;
        // 得到界面中层管理器子元素个数,从零开始计数
        final int sizeMid = bv.vWidgetArray_.size();
        Object o = null;
        needsettleComponetsAgainSelect = null;
        // 此循环处理当前form的联动
        for (int i = 0; i < sizeMid; i++) {
            // 得到界面中层管理框架中的单个子元素
            o = bv.vWidgetArray_.elementAt(i);
            if (o == null) {
				continue;
			}
            if (o instanceof Wrap)
                continue;
            // 下拉框控件中的元素不参加此联动操作
            if (o instanceof Select.Option)
                continue;
            if (o instanceof Component) {
                Component c = (Component) o;
                FormLayout formLayout = c.getForm();
                // 如果控件被包含在form里面，但是该form不可见，则不执行此联动
                if (null != formLayout && !formLayout.isShown()) {
                    continue;
                }
                if (null != formLayout && null != component.getForm()) {
                    nameFormTemp = formLayout.attrName_;
                    if (null != component.getForm().attrName_ && !component.getForm().attrName_.equals(nameFormTemp))
                        continue;
                }

            }
            view = (View) o;
            settleComponets(bv, view, isWorked, relaEnable, relaDisable, relaVisible, relaInvisible);
        }
        // 重新联动一次本应加到form管理器却未加进的控件
        gangedInForm(bv);
      //此处做特殊处理，如果上面的联动显示了一个包含有Select的table，那么继续对这个select再触发一次联动
        if (needsettleComponetsAgainSelect != null) {
        	needsettleComponetsAgainSelect.getCurrentOption().settleComponetOption(bv, true, 0);
        }
    }

    /**
     * 由于有些原本应该在form管理器里面的控件没有加载到form管理器里面，所以要通过这个方法再一次触发一下控件的联动设置。
     */
    public static void gangedInForm(final BaseView bv) {
        // 得到界面中层管理器子元素个数,从零开始计数
        final int sizeMid = bv.vWidgetArray_.size();
        bv.runOnUiThread(new Runnable() {

            public void run() {
                // 次循环处理刚转换为可见状态form的联动
                for (int i = 0; i < sizeMid; i++) {
                    // 得到界面中层管理框架中的单个子元素
                    Object o = bv.vWidgetArray_.elementAt(i);
                    if (o instanceof Wrap)
                        continue;
                    if (o instanceof FormLayout) {
                        final FormLayout formLayout = (FormLayout) o;
                        final boolean isWorked = formLayout.isShown();
                        final int size = formLayout.getChildCount();
                        if (size == 0) {
                            // 该判断条件是以前的框架遗漏造成，有些控件属于这个form，但是却不存在form管理器里面。 此时比对form和各控件的关键字来进行联动筛选。
                            // final int sizeTemp = sizeMid;
                            String flName = formLayout.attrName_;
                            if (null == flName)
                                continue;
                            for (int j = 0; j < sizeMid; j++) {
                                Object oTemp = bv.vWidgetArray_.elementAt(j);
                                if (null == oTemp)
                                    continue;
                                if (oTemp instanceof Wrap)
                                    continue;
                                if (oTemp instanceof FormLayout) {
                                } else {
                                    Component cTemp = (Component) oTemp;
                                    FormLayout flTemp = cTemp.getForm();
                                    if (null != flTemp && null != flTemp.attrName_ && flName.equals(flTemp.attrName_)) {
                                        View viewTemp = (View) oTemp;
                                        viewTemp.setVisibility(isWorked ? View.VISIBLE : View.GONE);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
    }

    private static void settleComponets(final BaseView bv, final View view, final boolean isWorked, final String[] relaEnable, final String[] relaDisable, final String[] relaVisible, final String[] relaInvisible) {
        if (view == null)
            return;
        if (null == view.getTag()) {
            // 如果控件名为空，则直接跳出本次循环。
            return;
        }
        // 得到控件标志名，里面存储的都是每个控件的“name”属性
        final String nameView = view.getTag().toString();
        // TODO Auto-generated method stub
        bv.runOnUiThread(new Runnable() {

            public void run() {
                if (null != relaEnable) {
                    final int sizeEnable = relaEnable.length;
                    for (int i = 0; i < sizeEnable; i++) {
//                        if (null != relaEnable[i] && relaEnable[i].indexOf(nameView) != -1) {
                    	if (null != relaEnable[i] && relaEnable[i].equals(nameView)) {
                            view.setEnabled(isWorked);
                        }
                    }
                }
                if (null != relaDisable) {
                    final int sizeDisable = relaDisable.length;
                    for (int i = 0; i < sizeDisable; i++) {
//                        if (null != relaDisable[i] && relaDisable[i].indexOf(nameView) != -1) {
                    	if (null != relaDisable[i] && relaDisable[i].equals(nameView)) {
                            view.setEnabled(!isWorked);
                        }
                    }
                }

                if (null != relaVisible) {
                    final int sizeVisibility = relaVisible.length;
                    for (int i = 0; i < sizeVisibility; i++) {
//                        if (null != relaVisible[i] && relaVisible[i].indexOf(nameView) != -1) {
                    	if (null != relaVisible[i] && relaVisible[i].equals(nameView)) {
                            if (view instanceof Table && view.getParent() instanceof LPLinearLayoutView) {
                            	//如果是table被联动，但table超宽，只需要让table的父窗口联动
                            	((View)view.getParent()).setVisibility(isWorked ? View.VISIBLE : View.GONE);
                            	getSelectInVisibleTable ((Table) view);
                            } else {
                            	view.setVisibility(isWorked ? View.VISIBLE : View.GONE);
                            	if (view instanceof Table) {
                            		getSelectInVisibleTable ((Table) view);
                            	}
                            }
                            if (view instanceof mTextField && !view.isFocusableInTouchMode()) {
                                view.setFocusableInTouchMode(true);
                            }
                            if (view.isShown() == isWorked) {
                                if (view instanceof Select) {
                                    Select temp = (Select) view;
                                    temp.cleanText();
                                }
                            }
                        }
                    }
                }
                if (null != relaInvisible) {
                    final int sizeInvisible = relaInvisible.length;
                    for (int i = 0; i < sizeInvisible; i++) {
//                        if (null != relaInvisible[i] && relaInvisible[i].indexOf(nameView) != -1) {
                    	if (null != relaInvisible[i] && relaInvisible[i].replace("	", "  ").trim().equals(nameView)) {
                            
                            if (view instanceof Table && view.getParent() instanceof LPLinearLayoutView) {
                            	//如果是table被联动，但table超宽，只需要让table的父窗口联动
                            	((View)view.getParent()).setVisibility(isWorked ? View.GONE : View.VISIBLE);
                            } else {
                            	view.setVisibility(isWorked ? View.GONE : View.VISIBLE);
                            }
                            if (view.isShown() != isWorked) {
                                if (view instanceof Select) {
                                    Select temp = (Select) view;
                                    temp.cleanText();
                                }
                            }
                        }
                    }
                }
            }

        });
    }

    private static void getSelectInVisibleTable (Table table) {
    	for(int i = table.cells_.size() - 1; i >= 0; i--) {
    		Table.Cell cell = table.cells_.elementAt(i);
    		for(int j = cell.cellItems.size() - 1; j >= 0; j--) {
    			Component cp = (Component)cell.cellItems.get(j);
    			if (cp instanceof Select) {
    				needsettleComponetsAgainSelect = (Select)cp;
    				return;
    			}
    		}
    	}
    }
    
    // 设置控件之间的联动关系
    public static void settleComponets(BaseView bv) {
        // 得到界面中层管理器子元素个数,从零开始计数
        // int sizeMid = bv.tabBar_.getContentChildCount();
        int sizeMid = bv.vWidgetArray_.size();
        View view = null;
        Object o;
		
        for (int i = 0; i < sizeMid; i++) {
            // 得到界面中层管理框架中的单个子元素
            o = bv.vWidgetArray_.elementAt(i);
            if (o instanceof Wrap)
                continue;
            if (o instanceof View) {
                // 如果该控件不可见，也不执行联动操作
                if (!((View) o).isShown())
                    continue;
            }
            if (o instanceof Component) {
                Component c = (Component) o;
                FormLayout formLayout = c.getForm();
                // 如果控件被包含在form里面，但是该form不可见，则不执行此联动
                if (null != formLayout && !formLayout.isShown()) {
                    continue;
                }
            }
            // 该处由于线程问题导致界面控件未参加联动,暂时添加该句,以后线程问题有待修改
//            System.err.println(o.getClass().toString());
            view = (View) o;
            if (view instanceof Radio) {
                Radio tempRadio = (Radio) view;
                tempRadio.settleComponetsRadio(bv, i);
            } else if (view instanceof cCheckBox) {
                cCheckBox temp = (cCheckBox) view;
                temp.settleComponets(bv, i);
            } else if (view instanceof Select) {
                Select temp = (Select) view;
                if (temp.optionV_ != null) {
                    int sizeSelect = temp.optionV_.size();
                    Select.Option option = null;
                    for (int k = 0; k < sizeSelect; k++) {
                        option = (Select.Option) temp.optionV_.elementAt(k);
                        option.settleComponetOption(bv, false, i);
                    }
                }
            } else if (view instanceof SegmentLinearLayout) {
                SegmentLinearLayout sll = (SegmentLinearLayout) view;
                int size = sll.getChildCount();
                Radio tempRadio;
                for (int j = 0; j < size; j++) {
                    tempRadio = (Radio) sll.getChildAt(j);
                    tempRadio.settleComponetsRadio(bv, i);
                }
            }
        }

        for (int i = 0; i < sizeMid; i++) {
            // 执行选中控件状态的联动
            // 得到界面中层管理框架中的单个子元素
            o = bv.vWidgetArray_.elementAt(i);
            if (o instanceof Wrap)
                continue;

            view = (View) o;

            if (view instanceof Radio) {
                // 设置选中的单选联动
                Radio temp = (Radio) view;
                if (temp.isChecked()) {
                    temp.settleComponetsRadio(bv, i);
                }
            } else if (view instanceof Table) {
                Table table = (Table) view;
                for (int j = 0; j < table.cells_.size(); j++) {
                    Table.Cell cell = (Table.Cell) table.cells_.elementAt(j);
                    for (int k = 0; k < cell.size(); k++) {
                        View tbcmp = (View) cell.elementAt(k);
                        if (tbcmp instanceof Radio) {
                            Radio tbrd = (Radio) tbcmp;
                            if (tbrd.isChecked()) {
                                tbrd.settleComponetsRadio(bv, i);
                            }
                        }
                    }
                }
            } else if (view instanceof SegmentLinearLayout) {
                SegmentLinearLayout sll = (SegmentLinearLayout) view;
                int size = sll.getChildCount();
                Radio tempRadio;
                for (int j = 0; j < size; j++) {
                    tempRadio = (Radio) sll.getChildAt(j);
                    if (tempRadio.isChecked()) {
                        tempRadio.settleComponetsRadio(bv, i);
                    }
                }
            } else if (view instanceof Select) {
                // 设置选中的下拉框控件联动
                Select temp = (Select) view;
                if (temp.dropdownMenuText_ != null) {
                    Select.Option option = null;
                    // 再执行一次选中控件的联动关系
//                    option = (Select.Option) temp.dropdownMenuText_.elementAt(temp.currentMenu_);
                    FormAction faction = bv.getFormByComponent(view);
                    if(temp.attrSave_&&(Mid.savePropertyTemp_.get(faction.action_.concat(temp.attrName_))!=null)){
                    	option = temp.getOption((String) Mid.savePropertyTemp_.get(faction.action_.concat(temp.attrName_)));
                    } else {
                    	option = (Select.Option) temp.dropdownMenuText_.elementAt(temp.currentMenu_);
                    }
                    
                    // 设置下拉框控件与下拉框控件之间的部分联动效果（该效果仅影响下拉框显示的option内容）
                    if (null != option && null != option.selt_) {
                        option.selt_.dropdownMenuClickItem();
                        // 设置下拉框控件和非下拉框控件的联动效果
                        option.settleComponetOption(bv, true, i);
                        option.postInvalidate();
                    }
                }
            }
        }
        
        Select.Option option = null;
        for (int i = 0; i < sizeMid; i++) {
            // 重新执行一次存储操作
            // 得到界面中层管理框架中的单个子元素
            o = bv.vWidgetArray_.elementAt(i);
            if (o instanceof Wrap)
                continue;

            view = (View) o;
            if (view instanceof Select && view.isShown()) {
                FormAction faction = bv.getFormByComponent(view);
                Select temp = (Select) view;
                if (temp.attrSave_) {
                    if (null != Mid.savePropertyTemp_ && null != faction.action_&& null != temp.attrName_) {
                      	if(Mid.savePropertyTemp_.get(faction.action_.concat(temp.attrName_))==null){
                    		return;
                    	}
                    	 String cacheLabel = (String) Mid.savePropertyTemp_.get(faction.action_.concat(temp.attrName_));
                         option = temp.getOption(cacheLabel);
                        if (null != option) {
                            // 如果服务端来的xml中下拉框控件里面含有save属性，且缓存中存在对应的option存储内容，则将该存储内容取出来作为下拉框控件的显示对象
                            String value1 = option.value_;
                            String value2 = "";
                            Select.Option optionTemp = null;
                            final int size = temp.optionV_.size();
                            // 表示该下拉框控件为普通下拉框控件
                            for (int j = 0; j < size; j++) {
                                optionTemp = (Select.Option) temp.optionV_.elementAt(j);
                                value2 = optionTemp.value_;
                                if (value1.equals(value2)) {
                                    temp.setCurrentMenu(j);
                                    temp.setText(option.label_);
                                }
                            }
                        }
                    }
                }
                if(null!=faction.action_&&null!=temp.attrName_){
                	Mid.savePropertyTemp_.remove(faction.action_.concat(temp.attrName_)); 
                }
            } else if (view instanceof mTextField) {
				mTextField temp = (mTextField) view;
				if (temp.attrSave_
						&& Mid.savePropertyTemp_.get(temp.attrName_) != null) {
					String strTemp = (String) Mid.savePropertyTemp_
							.get(temp.attrName_);
					temp.setText(strTemp);
					Mid.savePropertyTemp_.remove(temp.attrName_);
				}
			}
        }
    }

    public static void init(Activity app) {
        try {
        	progress_ = ConstantRepository.decodeBitmap(app.getResources(), R.drawable.progindr);
        } catch (Exception ex) {
            Utils.printOutToConsole("Utils-init:" + ex.toString());
        }
    }

    static boolean isLeftSoftKey(int key) {

        return (key == LEFT_SOFTKEY);
    }

    static boolean isRightSoftKey(int key) {
        // Motorola some phones's right key is -22, and other is 22.
        // return (key == RIGHT_SOFTKEY || key == -RIGHT_SOFTKEY);
        return (key == RIGHT_SOFTKEY);
    }

    static int getLeftSoftKey() {
        return LEFT_SOFTKEY;
    }

    static int getRightSoftKey() {
        return RIGHT_SOFTKEY;
    }

    /**
     * Graphics.drawRegion() has a bug in 4.2.1 and we have to use a replacement function.
     */
    public static void drawRegion(Canvas g, Bitmap img, int srcX, int srcY, int width, int height, int dstX, int dstY) {
        g.drawBitmap(img, new Rect(srcX, srcY, srcX + width, srcY + height), new Rect(dstX, dstY, dstX + width, dstY
                + height), new Paint());
    }

    static int fixTransparentPixel(int pixel) {
        // We don't use semitransparent pixel if the phone only support for full
        // transparency and full opacity.
        if (numAlphaLevel_ > 2 && (pixel & 0xff000000) != 0)
            return (pixel & 0x00ffffff) + ConfigManager.DEFAULT_TRANSPARENCY;
        else
            return pixel;
    }

    /**
     * Given an image, assign transparency value to its non-background pixels (background pixels are pixels that are
     * completely transparent).
     * 
     * @param transparency
     *            255 == totally opaque.
     */
    public static final Bitmap fixTransparentImage(Bitmap img) throws Exception {
        int width = img.getWidth();
        int height = img.getHeight();
        int sz = width * height;
        int[] rgb = new int[sz];
        // Params: (rgb, offset, scanlength, x, y, width, height)
        // rgbData[offset + (a - x) + (b - y) * scanlength] = P(a, b);
        img.getPixels(rgb, 0, width, 0, 0, width, height);
        for (int i = 0; i < sz; ++i) {
            rgb[i] = fixTransparentPixel(rgb[i]);
        }
        img = Bitmap.createBitmap(rgb, width, height, Bitmap.Config.RGB_565);
        return img;
    }


    public static final String abbrevString(String title, Paint font, int maxWidth) {
        if (title == null)
            return "";
        if (font.measureText(title) > maxWidth) {
            int pos = nextLinePosition(title.toCharArray(), 0, font, maxWidth, font.getTextWidths(ELLIPSIS, 0,
                    ELLIPSIS.length, new float[ELLIPSIS.length]));
            if (pos == -1)
                return title;
            else
                return title.substring(0, pos) + "...";
        } else
            return title;
    }

    static final String appendDots(String src, Paint font, int maxWidth) {
        if (src == null || font == null || maxWidth < 0) {
            return null;
        }
        String dest = null;
        dest = src + "...";
        while (font.measureText(dest) > maxWidth) {
            dest = src.substring(0, src.length() - 2) + "...";
        }
        return dest;
    }

    private static final char ELLIPSIS[] = { '.', '.', '.' };

    public static final int getEllipsisWidth(Paint f) {
        return f.getTextWidths(ELLIPSIS, 0, ELLIPSIS.length, new float[ELLIPSIS.length]);
    }

    /**
     * Is this character whitespace?
     */
    public static final boolean isWhitespace(char ch) {
        return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
    }

    /**
     * Case insensitive string match
     * 
     * @param ignoreCase
     *            if true, ignore case
     * @param s1
     * @param s2
     */
    public static boolean stringMatch(boolean ignoreCase, String s1, String s2) {
        int cmplen = Math.max(s1.length(), s2.length());
        if ((s1 == null) || (s2 == null)) {
            return false;
        }
        return s1.regionMatches(true, 0, s2, 0, cmplen);
    }

    /**
     * Given a starting position in a string, return the next position that this string should be split if it cannot fit
     * within the given width. If it does not fit, we will include an ellipsis at the end to indicate broken line. If it
     * does fit, we return -1.
     */
    public static final int nextLinePosition(char[] str, int pos, Paint f, int maxWidth, int ellWidth) {
        int strWidth = 0;
        while (pos < str.length) {
            if (str[pos] == '\n') {
                return pos;
            }
            strWidth += f.measureText(String.valueOf(str[pos]));
            if (strWidth + ellWidth > maxWidth) {
                // If the rest of string can fit instead of the ellipsis, put it
                // there.
                // int tmp = f.getTextWidths(str, pos + 1, str.length - pos - 1,
                // new float[str.length - pos - 1]);
                int tmp = (int) f.measureText(str, pos + 1, str.length - pos - 1);
                if (strWidth + tmp <= maxWidth) {
                    return -1;
                } else {
                    return pos;
                }
            }
            ++pos;
        }
        return -1;
    }

    /**
     * Starting from pos in str, find the longest string that fits in maxLineWidth. If doesn't fit, break the line by
     * hyphenation or at a line break point.
     * 
     * If newLine is true, we are starting from a new line and should get rid of initial white spaces.
     * 
     * Returns the position of the next character to be scanned in str after this line break.
     */
    public static final int nextLineLayout(char[] str, int pos, Paint f, int maxLineWidth, int hyphenWidth,
            int[] linebreak, boolean newLine) {
        int strWidth = 0;
        int startPos = pos;
        int lastBreakPoint = pos;

        // Filter out initial white spaces at start of a line.
        if (newLine) {
            while (pos < str.length && (str[pos] == ' ' || str[pos] == '\t'))
                ++pos;
        }

        linebreak[LBI_START] = pos;
        while (pos < str.length) {
//            boolean punct = false;
            switch (str[pos]) {
            // NOTE: don't recognize CR because in XML, only <br> or <p> should
            // matter.
            case '\n':
                // Insert a newline.
                linebreak[LBI_BREAK] = pos - 1;
                linebreak[LBI_NEXT] = pos + 1;
                linebreak[LBI_TYPE] = LB_SKIP;
                return pos + 1;
            case '<': {
                // Look ahead to see if we have a <p>, <br>, <p/>, <br/>, </p>,
                // </br>, <b> <tr> <td>
                // XXX We ignore complex cases, such as newlines are inserted
                // into tags.
                // NOTE: the 32 limit is an arbitrary one
                int endPos = pos;
                while (endPos < (str.length - 1) && endPos - pos < 8) {
                    ++endPos;
                    if (str[endPos] == '>') {
                        int pp1 = pos + 1;
                        int pp2 = pos + 2;
                        int pp3 = pos + 3;
                        char ch_pp1 = Character.toLowerCase(str[pp1]);
                        if (ch_pp1 == 'p' && (pp2 == endPos || str[pp2] == '/' || str[pp2] == ' ')) {
                            linebreak[LBI_BREAK] = pos - 1;
                            linebreak[LBI_NEXT] = endPos + 1;
                            linebreak[LBI_TYPE] = LB_PARAGRAPH; // Paragraph
                            return endPos + 1;
                        } else if (ch_pp1 == 'b'
                                && (pp2 == endPos || (Character.toLowerCase(str[pp2]) == 'r' && (pp3 == endPos
                                        || str[pp3] == '/' || str[pp3] == ' ')))) {
                            linebreak[LBI_BREAK] = pos - 1;
                            linebreak[LBI_NEXT] = endPos + 1;
                            // Only add newline if this is a br.
                            linebreak[LBI_TYPE] = (pp2 == endPos) ? LB_SKIP : LB_NEWLINE;
                            return endPos + 1;
                        } else if (ch_pp1 == '/' || ch_pp1 == 'i' || ch_pp1 == 'e' || ch_pp1 == 's' || ch_pp1 == 'c'
                                || ch_pp1 == 't' || ch_pp1 == 'h') {

                            // Ignore <em>, <strong>, <center>
                            // Ignore all kinds of end tags.
                            linebreak[LBI_BREAK] = pos - 1;
                            linebreak[LBI_NEXT] = endPos + 1;
                            linebreak[LBI_TYPE] = LB_SKIP;
                            return endPos + 1;
                        }
                    }
                }
                // XXX FIXME: Ignore <a href=...> and <font ...>, <a target...>,
                // <a title...>, <a rel...> here. We will capture the hyper link
                // and tie it to the link body later.
                char ch_pp1 = Character.toLowerCase(str[pos + 1]);
                if (str.length - pos >= 5 && (ch_pp1 == 'a' || ch_pp1 == 'f')) {
                    if (ch_pp1 == 'a') {
                        // Skip spaces between a and href
                        endPos = pos + 2;
                        while (endPos < str.length && str[endPos] == ' ')
                            ++endPos;
                    } else {
                        endPos = pos + 1;
                    }
                    if (str.length - endPos > 3) {
                        ch_pp1 = Character.toLowerCase(str[endPos]);
                        char ch_pp2 = Character.toLowerCase(str[endPos + 1]);
                        char ch_pp3 = Character.toLowerCase(str[endPos + 2]);
                        char ch_pp4 = Character.toLowerCase(str[endPos + 3]);
                        if ((ch_pp1 == 'h' && ch_pp2 == 'r' && ch_pp3 == 'e' && ch_pp4 == 'f')
                                || (ch_pp1 == 'f' && ch_pp2 == 'o' && ch_pp3 == 'n' && ch_pp4 == 't')
                                || (ch_pp1 == 't' && ch_pp2 == 'a' && ch_pp3 == 'r' && ch_pp4 == 'g')
                                || (ch_pp1 == 't' && ch_pp2 == 'i' && ch_pp3 == 't' && ch_pp4 == 'l')
                                || (ch_pp1 == 'r' && ch_pp2 == 'e' && ch_pp3 == 'l')) {
                            // Ignore everything, including newline, till next
                            // '>'
                            while (endPos < str.length && str[endPos] != '>')
                                ++endPos;
                        }
                    }
                    linebreak[LBI_BREAK] = pos - 1;
                    if (endPos + 1 < str.length)
                        linebreak[LBI_NEXT] = endPos + 1;
                    else
                        linebreak[LBI_NEXT] = str.length - 1;
                    linebreak[LBI_TYPE] = LB_SKIP;
                    return endPos + 1;
                }
                // XXX FIXME: Ignore <p class=...> & <img src=...>,<span ...>
                // <lp...> , </lp:...>, <table > <div>here. We will capture the
                // hyper link
                // and tie it to the link body later.
                if (str.length - pos >= 8
                        && (ch_pp1 == 'p' || ch_pp1 == 'i' || ch_pp1 == 'l' || ch_pp1 == 's' || ch_pp1 == 't' || ch_pp1 == 'd')
                        || ch_pp1 == '/') {
                    endPos = pos + 2;
                    // Ignore everything, including newline, till next '>'
                    while (endPos < str.length && str[endPos] != '>')
                        ++endPos;

                    linebreak[LBI_BREAK] = pos - 1;
                    linebreak[LBI_NEXT] = endPos + 1;
                    linebreak[LBI_TYPE] = LB_SKIP;
                    return endPos + 1;
                }

                // For tags that we do not recognize, fall through.
            }
            case ' ':
            case '\t':
                lastBreakPoint = pos;
                // fall through
            default:
                // Check one more character to see if it fits current string. If
                // not,
                // try to break at the last line break point. If that is too far
                // away,
                // add a hyphen at this place.
                strWidth += f.measureText(String.valueOf(str[pos]));
                if (strWidth >= maxLineWidth) {
                    // This was meant for hyphenation. When we insert a newline,
                    // can do that right at the starting point.
                    if (lastBreakPoint == startPos) {
                        lastBreakPoint = (pos == startPos) ? pos : (pos - 1);
                    }
                    linebreak[LBI_BREAK] = lastBreakPoint - 1;
                    linebreak[LBI_NEXT] = lastBreakPoint;
                    linebreak[LBI_TYPE] = LB_NEWLINE;
                    return lastBreakPoint;
                }
            }
            ++pos;
        }
        return -1;
    }

    /**
     * Starting from pos in str, find the longest string that fits in maxLineWidth.
     * 
     * Don't need to check
     * <p>
     * , <br>
     * ,
     * <p/>
     * , <br/>
     * ,
     * </p>
     * , </br>, <b>
     * <tr>
     * <td>again. They should be parsed by HTML.
     */
    public static final int getLineEndIndex(char[] chars, int pos, Paint f, int LineWidth, int[] linebreak, boolean newLine,
            boolean isTrimHeadBlank, boolean isBreakWord) {
        if (chars == null || f == null)
            return -1;
        int strWidth = 0;
        int startPos = pos;
        int lastBreakPoint = pos;
        // Filter out initial white spaces at start of a line.
        if (newLine) {
            if (isTrimHeadBlank) {
                while (pos < chars.length && (chars[pos] == ' ' || chars[pos] == '\t'))
                    ++pos;
            } else {
                while (pos < chars.length && chars[pos] == '\t')
                    ++pos;
            }
        }
        linebreak[LBI_START] = pos;
        while (pos < chars.length) {
            switch (chars[pos]) {
            // NOTE: don't recognize CR because in XML, only <br> or <p> should
            // matter.
            case '\n':
                chars[pos] = ' ';
                return pos;
            case ' ':
            case '.':
            case '/':
            case '\t':
                lastBreakPoint = pos + 1;
            default:
                // Check one more character to see if it fits current string. If
                // not,
                // try to break at the last line break point.
                strWidth += f.measureText(String.valueOf(chars[pos]));
                if (strWidth > LineWidth) {
                    if (isBreakWord) {
                        return pos - 1;
                    } else {
                        // It is possible that a word's width bigger than line
                        // width.
                        if (lastBreakPoint == startPos && pos > startPos && newLine) {
                            return pos - 1;
                        } else {
                            return lastBreakPoint;
                        }
                    }
                }
            }
            ++pos;
        }
        return chars.length;
    }

    public static final boolean isPunct(char ch) {
        switch (ch) {
        case '.':
        case ',':
        case '?':
        case '!':
        case '\'':
        case '"':
        case ':':
        case ';':
        case '-':
            return true;
        }
        return false;
    }

    static final String escapeHTML(String str) {
        if (str == null)
            return null;
        StringBuffer sb = new StringBuffer();
        int num = str.length();
        for (int i = 0; i < num; i++) {
            char ch = str.charAt(i);
            switch (ch) {
            case '<':
                sb.append("&lt;");
                break;
            case '>':
                sb.append("&gt;");
                break;
            case '&':
                sb.append("&amp;");
                break;
            case '"':
                sb.append("&quot;");
                break;
            case ' ':
                sb.append("&nbsp;");
                break;
            default:
                sb.append(ch);
                break;
            }
        }
        return sb.toString();
    }

    /**
     * Unescape a HTML string by filtering out &...; sequences, including &#<numbers>;. We do not consider the case
     * where one sequence is broken into multiple lines.
     */
    public static final String unescapeHTML(String str) {
        char[] src = str.toCharArray();
        char[] dest = new char[src.length];
//        boolean foundAmber = false;
        int escapeIdx = -1;
        int dstIdx = 0;
        int j;
        int ch;

        for (int i = 0; i < src.length; i++) {
            switch (src[i]) {
            case '&':
                // we should not miss the case &aaa&.
                while (escapeIdx > 0 && escapeIdx < i) {
                    dest[dstIdx++] = src[escapeIdx++];
                }
                escapeIdx = i;
                break;
            case ';':
                if (escapeIdx >= 0) {
                    if (src[escapeIdx + 1] == '#') {
                        ch = 0;
                        for (j = escapeIdx + 2; j < i; ++j) {
                            if (src[j] < '0' || src[j] > '9') {
                                ch = -1;
                                break;
                            } else {
                                ch *= 10;
                                ch += src[j] - '0';
                            }
                        }
                    } else {
                        int pp1 = escapeIdx + 1;
                        int pp2 = escapeIdx + 2;
                        int pp3 = escapeIdx + 3;
                        int pp4 = escapeIdx + 4;
                        int pp5 = escapeIdx + 5;
                        if (src[pp1] == 'q' && src[pp2] == 'u' && src[pp3] == 'o' && src[pp4] == 't' && pp5 == i)
                            ch = '"';
                        else if (src[pp1] == 'a' && src[pp2] == 'm' && src[pp3] == 'p' && pp4 == i)
                            ch = '&';
                        else if (src[pp1] == 'l' && src[pp2] == 't' && pp3 == i)
                            ch = '<';
                        else if (src[pp1] == 'g' && src[pp2] == 't' && pp3 == i)
                            ch = '>';
                        else if (src[pp1] == 'n' && src[pp2] == 'b' && src[pp3] == 's' && src[pp4] == 'p' && pp5 == i)
                            ch = ' ';
                        else
                            ch = -1;
                        if (ch != -1) {
                            dest[dstIdx++] = (char) ch;
                            escapeIdx = -1;
                            break;
                        }
                    }
                } else
                    ch = -1;

                // Replace the Html Special Characters likes &#<numbers>.
                if (ch >= 0) {
                    switch (ch) {
                    case 123:
                        ch = '{';
                        break;
                    case 125:
                        ch = '}';
                        break;
                    case 133:
                        for (int k = 0; k < 3; k++)
                            dest[dstIdx++] = '.';
                        ch = -1;
                        break;
                    case 146:
                        ch = '\'';
                        break;
                    case 147:
                    case 148:
                        ch = '"';
                        break;
                    case 151:
                        ch = '-';
                        break;
                    default:
                        ch = ' ';
                        break;
                    }
                    if (ch != -1)
                        dest[dstIdx++] = (char) ch;
                } else {
                    // If current charactor is only a characters ";" ,
                    // not a Html Special Characters, we copy it in dest.
                    if (escapeIdx < 0)
                        dest[dstIdx++] = src[i];
                    else {
                        for (j = escapeIdx; j <= i; ++j)
                            dest[dstIdx++] = src[j];
                    }
                }
                escapeIdx = -1;
                break;
            default:
                if (escapeIdx < 0)
                    dest[dstIdx++] = src[i];
                else if (escapeIdx > 0 && ((i - escapeIdx) > 5)) {
                    for (int k = escapeIdx; k <= i; k++) {
                        dest[dstIdx++] = src[k];
                    }
                    escapeIdx = -1;
                }
                break;
            }
        }

        return String.valueOf(dest, 0, dstIdx);
    }

    /**
     * non-ASCII characters are encoded as: first using the UTF-8 algorithm to encode to a sequence of 2 or 3 bytes,
     * then each of these bytes is encoded as "%xx".
     */
    public static final String escapeURIComponent(String str) {
        printOutToConsole("str ====== " + str);
        if (str == null)
            return null;
        StringBuffer sbuf = new StringBuffer();
        int ch;
        int len = str.length();
        for (int i = 0; i < len; i++) {
            ch = str.charAt(i);
            if ('A' <= ch && ch <= 'Z') {
                sbuf.append((char) ch);
            } else if ('a' <= ch && ch <= 'z') {
                sbuf.append((char) ch);
            } else if ('0' <= ch && ch <= '9') {
                sbuf.append((char) ch);
            } else if (ch == '-' || ch == '_' || ch == '.' || ch == '!' || ch == '~' || ch == '*' || ch == '\''
                    || ch == '(' || ch == ')') {
                sbuf.append((char) ch);
            } else if (ch < 0x0F) {
                sbuf.append('%');
                sbuf.append('0');
                sbuf.append(Integer.toHexString(ch));
            } else if (ch < 0x7F) {
                sbuf.append('%');
                sbuf.append(Integer.toHexString(ch));
            } else if (ch <= 0x07FF) { // non-ASCII characters and value <=
                // 0x7FF
                sbuf.append('%');
                sbuf.append(Integer.toHexString(0xc0 | (ch >> 6)));
                sbuf.append('%');
                sbuf.append(Integer.toHexString(0x80 | (ch & 0x3F)));
            } else { // non-ASCII characters and value <= 0xFFFF
                sbuf.append('%');
                sbuf.append(Integer.toHexString(0xe0 | (ch >> 12)));
                sbuf.append('%');
                sbuf.append(Integer.toHexString(0x80 | ((ch >> 6) & 0x3F)));
                sbuf.append('%');
                sbuf.append(Integer.toHexString(0x80 | (ch & 0x3F)));
            }
        }
        return sbuf.toString();
    }

    static final String unescapeURIComponent(String url) {
        if (url == null)
            return null;
        StringBuffer sbuf = new StringBuffer();
        int len = url.length();
        int ch;
        int b;
        int total = 0;
        int more = -1;
        int hb;
        int lb;
        for (int i = 0; i < len; i++) {
            switch (ch = url.charAt(i)) {
            case '%':
                ch = url.charAt(++i);
                hb = (Character.isDigit((char) ch) ? ch - '0' : 10 + Character.toLowerCase((char) ch) - 'a') & 0xF;
                ch = url.charAt(++i);
                lb = (Character.isDigit((char) ch) ? ch - '0' : 10 + Character.toLowerCase((char) ch) - 'a') & 0xF;
                b = (hb << 4) | lb;
                break;
            default:
                b = ch;
            }
            // Decode byte b as UTF-8, sumb collects incomplete chars
            if ((b & 0xc0) == 0x80) {
                total = (total << 6) | (b & 0x3f);
                if (--more == 0)
                    sbuf.append((char) total);
            } else if ((b & 0x80) == 0x00) {
                sbuf.append((char) b);
            } else if ((b & 0xe0) == 0xc0) {
                total = b & 0x1f;
                more = 1;
            } else if ((b & 0xf0) == 0xe0) {
                total = b & 0x0f;
                more = 2;
            } else if ((b & 0xf8) == 0xf0) {
                total = b & 0x07;
                more = 3;
            } else if ((b & 0xfc) == 0xf8) {
                total = b & 0x03;
                more = 4;
            } else {
                total = b & 0x01;
                more = 5;
            }
        }
        return sbuf.toString();
    }

    /**
     * Convert a string of double number to an integer, assuming the number is a coordinate.
     */
    public static final int strCoordToInt(String strDouble) {
//        char[] src = strDouble.toCharArray();
//        StringBuffer dst = new StringBuffer();
//        int digitsAfterDot = 0;
//        boolean dotFound = false;
//        for (int i = 0; i < src.length && digitsAfterDot < 6; i++) {
//            if (src[i] != '.') {
//                dst.append(src[i]);
//                if (dotFound) {
//                    ++digitsAfterDot;
//                }
//            } else {
//                dotFound = true;
//            }
//        }
//        // multiply by 1000000
//        for (int i = digitsAfterDot; i < 6; i++) {
//            dst.append('0');
//        }
//    	return (int)(Double.valueOf(strDouble) * 1000000);
        return Integer.parseInt(strDouble);
    }

    /**
     * Convert an integer coordinate into a float string.
     */
    public static final String intToFloatCoord(int coord) {
        StringBuffer buf = new StringBuffer();
        buf.append(coord);
        buf.insert(buf.length() - 6, '.');
        return buf.toString();
    }

    /**
     * Parse a ISO8601 date string and return it in a calendar object. Return UTC time.
     */
    public static long parseISO8601(String text) throws Exception {
        printOutToConsole(text);

        // Example date string: 2006-11-29T15:30:00.000-08:00
        int idx = text.indexOf('T');
        if (idx == -1) {
            // Invalid date
//            throw new IOException("错误的数据格式.");
        	  throw new IOException("网络数据格式异常。");
        }
        String date = text.substring(0, idx);
        int idx2 = text.indexOf('-', ++idx);
        String time;
        if (idx2 == -1) {
            time = text.substring(idx);
        } else {
            time = text.substring(idx, idx2);
        }

        idx = date.indexOf('-');
        int year = Integer.parseInt(date.substring(0, idx));
        idx2 = date.indexOf('-', ++idx);
        int month = Integer.parseInt(date.substring(idx, idx2));
        int day = Integer.parseInt(date.substring(++idx2));

        idx = time.indexOf(':');
        int hour = Integer.parseInt(time.substring(0, idx));
        idx2 = time.indexOf(':', ++idx);
        int min = Integer.parseInt(time.substring(idx, idx2));
        // The separater between seconds and time offset field can be 'Z' for
        // standard time,
        // or +/- for time zone offset.
        int idx3 = time.indexOf('+', ++idx2);
        String zoneString = null;
        int zoneOffset = 0; // time zone offset, in seconds
        if (idx3 == -1) {
            idx3 = time.indexOf('-', idx2);
        } else {
            zoneString = time.substring(idx3 + 1);
            zoneOffset = 1;
        }
        if (idx3 == -1) {
            idx3 = time.indexOf('Z', idx2);
        } else {
            zoneString = time.substring(idx3 + 1);
            zoneOffset = -1;
        }
        if (idx3 == -1) {
            idx3 = time.length();
        } else if (zoneString != null) {
            int idx4 = zoneString.indexOf(':', 0);
            if (idx4 != -1) {
                int zoneHour;
                int zoneMin;
                try {
                    zoneHour = Integer.parseInt(zoneString.substring(0, idx4));
                    zoneMin = Integer.parseInt(zoneString.substring(idx4 + 1));
                    zoneOffset *= zoneHour * 3600 + zoneMin * 60;
                } catch (Exception ignored) {
                    zoneOffset = 0;
                }
            }
        }
        int sec = 0;
        if (idx3 > idx2) {
            // Filter out sub-second component
            int idx4 = time.indexOf('.', idx2);
            if (idx4 != -1)
                idx3 = idx4;
            sec = Integer.parseInt(time.substring(idx2, idx3));
        }

        // Make a calendar time assuming that is UTC, then we'll make time zone
        // adjustment from UTC seconds.
        Calendar updatedDate = Calendar.getInstance();
        updatedDate.set(Calendar.YEAR, year);
        updatedDate.set(Calendar.MONTH, month - 1); // NOTE: month starts from
        // 0??
        updatedDate.set(Calendar.DAY_OF_MONTH, day); // Day start from 1??
        updatedDate.set(Calendar.HOUR_OF_DAY, hour);
        updatedDate.set(Calendar.MINUTE, min);
        updatedDate.set(Calendar.SECOND, sec);
        updatedDate.set(Calendar.MILLISECOND, 0);
        printOutToConsole("date: " + year + "-" + month + "-" + day + " " + hour + ":" + min + ":" + sec + " time "
                + updatedDate.getTime());
        printOutToConsole("timezone offset " + zoneOffset);
        return updatedDate.getTime().getTime() + zoneOffset * 1000;
    }

    /**
     * Displays a UTC time (in milliseconds) as MM/DD-HH:MM
     */
    public static void formatTimeString(long utc, StringBuffer str) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date(utc));
        str.append(cal.get(Calendar.MONTH) + 1); // NOTE: month starts from 0
        str.append("/");
        str.append(cal.get(Calendar.DAY_OF_MONTH));
        str.append("-");
        str.append(cal.get(Calendar.HOUR_OF_DAY));
        str.append(":");
        str.append(cal.get(Calendar.MINUTE));
    }

    /**
     * Displays a UTC time in milliseconds as YYYY/MM/DD
     */
    public static void formatDateString(long utc, StringBuffer str) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date(utc));
        str.append(cal.get(Calendar.YEAR));
        str.append("/");
        str.append(cal.get(Calendar.MONTH) + 1); // NOTE: month starts from 0
        str.append("/");
        str.append(cal.get(Calendar.DAY_OF_MONTH));
    }

    /**
     * Display a UTC time as format hh:mm am/pm
     */
    public static void fromatTimeAmPm(long utc, StringBuffer str) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date(utc));
        int hour = cal.get(Calendar.HOUR);
        int minu = cal.get(Calendar.MINUTE);
        if (hour < 10)
            str.append("0");
        str.append(hour);
        str.append(":");
        if (minu < 10)
            str.append("0");
        str.append(minu);
        if (cal.get(Calendar.AM_PM) == 0)
            str.append(" AM");
        else
            str.append(" PM");
    }


    /**
     * Parse simple state response XMLs from server and retrieve attributes from it. Used by UserManager, PoiRepository
     * (add/remove POI), etc.
     */
    public static String getXMLResponseAttribute(String reply, String attr, int startIndex, char matchCh) {
        int start = reply.indexOf(attr, startIndex);
        if (start < 0)
            return null;
        start += attr.length();
        int end = reply.indexOf(matchCh, start);
        if (end > start) {
            String s = reply.substring(start, end);
            return s;
        }
        return null;
    }

    /**
     * Check the email address whether is valid.
     */
    public static boolean checkEmail(String emailAdd) {
        int length = emailAdd.length();
        int temp1 = emailAdd.indexOf("@");
        int temp2 = emailAdd.indexOf(".");

        // temp1 > 1 means in this email address contains an “@” and there is a
        // user’s name before it.
        // temp2 != -1 means in this email address contains an "."
        // (length - temp1 > 3) means after “@” contains at least one letter
        // except “.”
        // (length - temp2 > 1) means "." is not the last letter
        if (temp1 > 1 && temp2 != -1 && (length - temp1 > 3) && (length - temp2 > 1)) {
            return true;
        } else
            return false;
    }

    /*
     * A Java implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS PUB 180-1 Copyright (C) Sam Ruby
     * 2004 All rights reserved
     * 
     * Based on code Copyright (C) Paul Johnston 2000 - 2002. See http://pajhome.org.uk/site/legal.html for details.
     * 
     * Converted to Java by Russell Beattie 2004 Base64 logic and inlining by Sam Ruby 2004 Bug fix correcting single
     * bit error in base64 code by John Wilson
     * 
     * BSD License
     * 
     * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
     * following conditions are met:
     * 
     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
     * disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
     * the following disclaimer in the documentation and/or other materials provided with the distribution.
     * 
     * Neither the name of the author nor the names of its contributors may be used to endorse or promote products
     * derived from this software without specific prior written permission.
     * 
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */

    // /*
    // * Bitwise rotate a 32-bit number to the left
    // */
    // private static int rol(int num, int cnt) {
    // return (num << cnt) | (num >>> (32 - cnt));
    // }
    /*
     * Take a string and return the base64 representation of its SHA-1.
     */
    public static String sha1(String str) throws Exception {

        // Convert a string to a sequence of 16-word blocks, stored as an array.
        // Append padding bits and the length, as described in the SHA1 standard

        byte[] x = str.getBytes("UTF-8");
        int[] blks = new int[(((x.length + 8) >> 6) + 1) * 16];
        int i;

        for (i = 0; i < x.length; i++) {
            blks[i >> 2] |= x[i] << (24 - (i % 4) * 8);
        }

        blks[i >> 2] |= 0x80 << (24 - (i % 4) * 8);
        blks[blks.length - 1] = x.length * 8;

        // calculate 160 bit SHA1 hash of the sequence of blocks

        int[] w = new int[80];

        int a = 1732584193;
        int b = -271733879;
        int c = -1732584194;
        int d = 271733878;
        int e = -1009589776;
        int num;

        for (i = 0; i < blks.length; i += 16) {
            int olda = a;
            int oldb = b;
            int oldc = c;
            int oldd = d;
            int olde = e;

            for (int j = 0; j < 80; j++) {
                if (j < 16) {
                    w[j] = blks[i + j];
                } else {
                    num = w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16];
                    w[j] = ((num << 1) | (num >>> (32 - 1)));
                }
                int t = ((a << 5) | (a >>> (32 - 5)))
                        + e
                        + w[j]
                        + ((j < 20) ? 1518500249 + ((b & c) | ((~b) & d)) : (j < 40) ? 1859775393 + (b ^ c ^ d)
                                : (j < 60) ? -1894007588 + ((b & c) | (b & d) | (c & d)) : -899497514 + (b ^ c ^ d));
                e = d;
                d = c;
                c = ((b << 30) | (b >>> (32 - 30))); // rol(b, 30);
                b = a;
                a = t;
            }

            a = a + olda;
            b = b + oldb;
            c = c + oldc;
            d = d + oldd;
            e = e + olde;
        }

        // Convert 160 bit hash to base64
        int[] words = { a, b, c, d, e, 0 };
        byte[] base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes();
        byte[] result = new byte[28];
        for (i = 0; i < 27; i++) {
            int start = i * 6;
            int word = start >> 5;
            int offset = start & 0x1f;

            if (offset <= 26) {
                result[i] = base64[(words[word] >> (26 - offset)) & 0x3F];
            } else if (offset == 28) {
                result[i] = base64[(((words[word] & 0x0F) << 2) | ((words[word + 1] >> 30) & 0x03)) & 0x3F];
            } else {
                result[i] = base64[(((words[word] & 0x03) << 4) | ((words[word + 1] >> 28) & 0x0F)) & 0x3F];
            }
        }
        result[27] = '=';

        return new String(result);
    }

    public static Bitmap bilinearResample(Bitmap oriImg, int newWidth, int newHeight) {
        return bilinearResample(oriImg, newWidth, newHeight, WHITE);
    }

    /**
     * Function for scale an image from a large to a smaller size, then return a new image with new size predefined.
     */
    public static Bitmap bilinearResample(Bitmap oriImg, int newWidth, int newHeight, int bgColor) {
        int oldW = oriImg.getWidth();
        int oldH = oriImg.getHeight();

        int[] ori_rgb = new int[oldW * oldH];
        int[] des_rgb = new int[newWidth * newHeight];

        oriImg.getPixels(ori_rgb, 0, oldW, 0, 0, oldW, oldH);

        int newIndex = 0;
        // draw each pixel in the new image
        for (int i = 1; i <= newHeight; i++) {
            // generate the y calculation variables
            int interplY = (i - 1) * oldH / newHeight;
            int calcY = (i - 1) * oldH % newHeight;

            for (int j = 1; j <= newWidth; j++) {
                // generate the x calculation variables
                int interplX = (j - 1) * oldW / newWidth;
                int calcX = (j - 1) * oldW % newWidth;

                int theColour1 = ori_rgb[(interplX) + (interplY) * oldW];
                int theColour2 = ori_rgb[(interplX + 1) + (interplY) * oldW];
                int theColour3 = ori_rgb[(interplX) + (interplY + 1) * oldW];
                int theColour4 = ori_rgb[(interplX + 1) + (interplY + 1) * oldW];

                // calculate the new colour
                int alpha1 = (theColour1 >> 24 & 0xFF) * (newHeight - calcY) / newHeight + (theColour3 >> 24 & 0xFF)
                        * calcY / newHeight;
                int alpha2 = (theColour2 >> 24 & 0xFF) * (newHeight - calcY) / newHeight + (theColour4 >> 24 & 0xFF)
                        * calcY / newHeight;
                int newAlpha = isOutofColor(alpha1 * (newWidth - calcX) / newWidth + alpha2 * calcX / newWidth);
                int newColor1r = (theColour1 >> 16 & 0xFF) * (newHeight - calcY) / newHeight
                        + (theColour3 >> 16 & 0xFF) * calcY / newHeight;
                int newColor2r = (theColour2 >> 16 & 0xFF) * (newHeight - calcY) / newHeight
                        + (theColour4 >> 16 & 0xFF) * calcY / newHeight;
                int newColorr = isOutofColor(newColor1r * (newWidth - calcX) / newWidth + newColor2r * calcX / newWidth);
                int newColor1g = (theColour1 >> 8 & 0xFF) * (newHeight - calcY) / newHeight + (theColour3 >> 8 & 0xFF)
                        * calcY / newHeight;
                int newColor2g = (theColour2 >> 8 & 0xFF) * (newHeight - calcY) / newHeight + (theColour4 >> 8 & 0xFF)
                        * calcY / newHeight;
                int newColorg = isOutofColor(newColor1g * (newWidth - calcX) / newWidth + newColor2g * calcX / newWidth);
                int newColor1b = (theColour1 & 0xFF) * (newHeight - calcY) / newHeight + (theColour3 & 0xFF) * calcY
                        / newHeight;
                int newColor2b = (theColour2 & 0xFF) * (newHeight - calcY) / newHeight + (theColour4 & 0xFF) * calcY
                        / newHeight;
                int newColorb = isOutofColor(newColor1b * (newWidth - calcX) / newWidth + newColor2b * calcX / newWidth);
                int newColor = ((newAlpha & 0xFF) << 24) | ((newColorr & 0xFF) << 16) | ((newColorg & 0xFF) << 8)
                        | (newColorb & 0xFF);

                // Set this pixel into the new image
                des_rgb[newIndex++] = newColor;
            }
        }

        Bitmap desImage = null;
        desImage = Bitmap.createBitmap(des_rgb, newWidth, newHeight, Bitmap.Config.RGB_565);
        // 缩放图片
        desImage = Bitmap.createScaledBitmap(desImage, newWidth, newHeight, true);
        if (desImage == null)
            desImage = oriImg;
        return desImage;
    }

    // it's used by the function bilinearResample().
    static int isOutofColor(int color) {
        if (color < 0)
            color = 0;
        if (color > 255)
            color = 255;
        return color;
    }

    // get num bits from data. the num should not bigger than 32.
    private static int getBits(byte[] data, int num) {
        int result = 0;
        int i = 0;
        if (bitIndex != 0) {
            i = 8 - bitIndex;
            result = bitByte >> bitIndex;
        }
        while (i < num) {
            bitByte = data[gIndex++] & 0xFF;
            result |= (bitByte << i);
            i += 8;
        }
        bitIndex = (bitIndex + num) & 0x7;// calculate (bitIndex + num)%8
        result &= (0xffffffff >>> (32 - num));
        return result;
    }

    // Get a code from data.
    private static int getCode(byte data[], int tree[]) {
        int node = tree[0];
        while (node >= 0) {
            if (bitIndex == 0)
                bitByte = (data[gIndex++] & 0xFF);
            node = (((bitByte & (1 << bitIndex)) == 0) ? tree[node >> 16] : tree[node & 0xFFFF]);
            bitIndex = (bitIndex + 1) & 0x7;
        }
        return (node & 0xFFFF);
    }

    // Decompress the literal/length code and the distance code.
    private static byte[] decompressCode(byte data[], int blTree[], int count) {
        int code = 0;
        byte previousCode = 0;
        int times = 0; // The number of the previous code's length need to
        // repeat.
        byte treeBits[] = new byte[count];
        int index = 0;
        while (index < count) {
            code = getCode(data, blTree);
            if (code == 16) {
                times = getBits(data, 2) + 3;
            } else if (code == 17) {
                times = getBits(data, 3) + 3;
                previousCode = 0;
            } else if (code == 18) {
                times = getBits(data, 7) + 11;
                previousCode = 0;
            } else {
                times = 0;
                previousCode = (byte) code;
                treeBits[index++] = (byte) code;
            }
            for (int i = 0; i < times; i++) {
                treeBits[index++] = previousCode;
            }
        }
        return treeBits;
    }

    // Get a huffman tree.
    private static int[] huffmanTree(byte bits[]) {
        int bl_count[] = new int[MAX_BITS + 1];
        for (int i = 0; i < bits.length; i++) {
            bl_count[bits[i]]++;
        }
        int code = 0;
        bl_count[0] = 0;
        int next_code[] = new int[MAX_BITS + 1];
        // Count the number of codes for each code length.
        for (int i = 1; i <= MAX_BITS; i++) {
            code = (code + bl_count[i - 1]) << 1;
            next_code[i] = code;
        }
        int tree[] = new int[((bits.length - 1) << 1) + MAX_BITS];
        int treeInsert = 1;
        for (int i = 0; i < bits.length; i++) {
            int len = bits[i];
            if (len != 0) {
                code = next_code[len]++;
                int node = 0;
                for (int bit = len - 1; bit >= 0; bit--) {
                    int value = code & (1 << bit);
                    if (value == 0) {
                        int left = tree[node] >> 16;
                        if (left == 0) {
                            tree[node] |= (treeInsert << 16);
                            node = treeInsert++;
                        } else
                            node = left;
                    } else {
                        int right = tree[node] & 0xFFFF;
                        if (right == 0) {
                            tree[node] |= treeInsert;
                            node = treeInsert++;
                        } else
                            node = right;
                    }
                }
                tree[node] = 0x80000000 | i;
            }
        }
        return tree;
    }

    public static int getColorFromString(String colorStr) {
        // default value is color Black
        if (colorStr == null)
            return BLACK;
        int color = switchColor(colorStr);
        if (color == -1 && colorStr.length() == 7) {
            int r, g, b;
            try {
                r = Integer.parseInt(colorStr.substring(1, 3), 16);
                g = Integer.parseInt(colorStr.substring(3, 5), 16);
                b = Integer.parseInt(colorStr.substring(5, 7), 16);
            } catch (Exception ex) {
                return BLACK;
            }
            color = ((r << 16) | (g << 8) | b);
        }
        if (color == -1)
            color = BLACK;
        return color;
    }

    // only support popular color because there is too many color.
    static int switchColor(String colorStr) {
        if (colorStr.indexOf("red") != -1)
            return 0xffff0000;
        else if (colorStr.indexOf("green") != -1)
            return 0xff00ff00;
        else if (colorStr.indexOf("blue") != -1)
            return 0xff0000ff;
        else if (colorStr.indexOf("gray") != -1)
            return 0xff808080;
        else if (colorStr.indexOf("white") != -1)
            return 0xffffffff;
        else if (colorStr.indexOf("yellow") != -1)
            return 0xffffff00;
        else
            return -1;
    }

    public static Bitmap createImgWaitLoad(Mid mid, String alt, int color, int w, int h) {
        Paint paint = new Paint();
        Bitmap imgWaitLoad;

        if (alt != null) {
            paint.setTypeface(Typeface.DEFAULT);
            paint.setTextSize(Utils.getScaledValue(ConfigManager.SIZE_IMGWAITLOAD));
//            w = (int) paint.measureText(alt) + 2;
            imgWaitLoad = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
            Canvas canvas = new Canvas(imgWaitLoad);
            paint.setColor(color);
            canvas.drawRect(0, 0, w, h, paint);
            paint.setColor(0xffffffff);
            int x = (w - ((int) paint.measureText(alt) + 2)) / 2 > 0 ? (w - ((int) paint.measureText(alt) + 2)) / 2 : 0;
            canvas.drawText(alt, x, h / 2, paint);
            if (!alt.equalsIgnoreCase("暂无图片")) 
            mid.waitDialog_.drawProcessing(canvas, w / 2 - Utils.progress_.getWidth() / 2,
                    (h + ConfigManager.SIZE_IMGWAITLOAD) / 2);
        } else {
            int wh = (int) (4 * paint.getTextSize());
            imgWaitLoad = Bitmap.createBitmap(wh, wh, Bitmap.Config.RGB_565);
            Canvas canvas = new Canvas(imgWaitLoad);
            canvas.drawRect(0, 0, wh - 1, wh - 1, paint);
            mid.waitDialog_.drawProcessing(canvas, wh / 2 - Utils.progress_.getWidth() / 2, wh / 2);
        }

        return imgWaitLoad;
    }

    /**
     * If we are on low memory or the photo can not be loaded, we will show a red cross in the photo frame.
     */
    static void createImageLoadFail(Canvas canvas) {
        Paint paint = new Paint();
        paint.setTypeface(Typeface.DEFAULT);
        int wh = (int) (4 * paint.getTextSize());
        canvas.drawRGB(0, 0, 0);
        canvas.drawRect(new Rect(0, 0, wh - 1, wh - 1), new Paint());
        canvas.drawRGB(255, 0, 0);
        int xStart = wh / 2 - 3;
        int yStart = wh / 2 - 3;

        canvas.drawLine(xStart, yStart, xStart + 6, yStart + 6, paint);
        canvas.drawLine(xStart, yStart + 1, xStart + 6, yStart + 7, paint);
        canvas.drawLine(xStart + 6, yStart, xStart, yStart + 6, paint);
        canvas.drawLine(xStart + 6, yStart + 1, xStart, yStart + 7, paint);
    }

    // It's used to decompress gzip data. Re. rfc1951 and rfc 1952.
    public static byte[] gunzip(byte[] gzipData) throws IOException {
        // Check if the data is gzip format and if it is used "deflate" compression method.
        if (gzipData[0] != 31 || gzipData[1] != -117)
            throw new IOException("压缩数据格式错误!");
        if (gzipData[2] != 8)
            throw new IOException("压缩数据方法错误!");

        // Skip the gzip data header.
        byte flg = gzipData[3];
        gIndex = 10;
        bitIndex = 0;
        bitByte = 0;
        if ((flg & 4) != 0)
            gIndex += getBits(gzipData, 16);
        if ((flg & 8) != 0)
            while (gzipData[gIndex++] != 0)
                ;
        if ((flg & 16) != 0)
            while (gzipData[gIndex++] != 0)
                ;
        if ((flg & 2) != 0)
            gIndex += 2;

        int temp = gIndex;
        gIndex = gzipData.length - 4;
        // The size of the original input data
        int size = getBits(gzipData, 16) | (getBits(gzipData, 16) << 16);
        byte[] unzipData = new byte[size];
        gIndex = temp;

        int unzipIndex = 0;
        bitIndex = 0;
        bitByte = 0;
        int lastBlock = 0; // 0 indicates have more block when 1 indicates it is the last block.
        int type = 0;// 0 indicates uncompress data, 1 indicates use static Huffman, 2 indicates use dynamic Huffman.
        while (lastBlock == 0) {
            lastBlock = getBits(gzipData, 1);
            type = getBits(gzipData, 2);
            if (type == 0) {
                // uncompress data
                bitIndex = 0;
                int length = getBits(gzipData, 16);
                gIndex += 2;
                System.arraycopy(gzipData, gIndex, unzipData, unzipIndex, length);
                gIndex += length;
                unzipIndex += length;
            } else {
                byte[] lBits;
                byte[] dBits;
                if (type == 1) {
                    // use static huffman.
                    lBits = new byte[288];// The lTree node numbers 286, the last two nodes is use for full tree.
                    for (int i = 0; i < 288; i++) {
                        if (i < 144 || i > 279) {
                            lBits[i] = 8;
                        } else if (i < 256) {
                            lBits[i] = 9;
                        } else {
                            lBits[i] = 7;
                        }
                    }
                    dBits = new byte[32];// The dTree node numbers 30, the last two nodes is use for full tree.
                    for (int i = 0; i < dBits.length; i++) {
                        dBits[i] = 5;
                    }
                } else if (type == 2) {
                    // use dynamic huffman.
                    int hlit = getBits(gzipData, 5) + 257;
                    int hdist = getBits(gzipData, 5) + 1;
                    int hclen = getBits(gzipData, 4) + 4;
                    byte[] bltreeBits = new byte[19];// The blTree node numbers 19.
                    for (int i = 0; i < hclen; i++)
                        bltreeBits[DYNAMIC_L_ORDER[i]] = (byte) getBits(gzipData, 3);
                    int[] blTree = huffmanTree(bltreeBits);
                    lBits = decompressCode(gzipData, blTree, hlit);
                    dBits = decompressCode(gzipData, blTree, hdist);
                } else {
                    throw new IOException("不能正确解压数据.");
                }

                int[] lTree = huffmanTree(lBits);// The literal/length tree.
                int[] dTree = huffmanTree(dBits);// The distance tree.
                int code = 0;
                while ((code = getCode(gzipData, lTree)) != 256) {// code=256 indicates the end of this block.
                    if (code < 256) {// literal byte
                        unzipData[unzipIndex++] = (byte) code;
                    } else {// length/distance pairs
                        code -= 257;
                        int length = EXTRA_L_VALUES[code];
                        if (EXTRA_L_BITS[code] > 0)
                            length += getBits(gzipData, EXTRA_L_BITS[code]);
                        code = getCode(gzipData, dTree);
                        int distance = EXTRA_D_VALUES[code];
                        if (EXTRA_D_BITS[code] > 0)
                            distance += getBits(gzipData, EXTRA_D_BITS[code]);
                        while (distance < length) {
                            System.arraycopy(unzipData, unzipIndex - distance, unzipData, unzipIndex, distance);
                            unzipIndex += distance;
                            length -= distance;
                        }
                        System.arraycopy(unzipData, unzipIndex - distance, unzipData, unzipIndex, length);
                        unzipIndex += length;
                    }
                }
            }
        }
        return unzipData;
    }

    static boolean isInComponent(int x, int y, View c) {
        if (c == null)
            return false;
        if (x < c.getLeft() || x > c.getLeft() + c.getWidth() || y < c.getTop() || y > c.getTop() + c.getHeight())
            return false;
        else
            return true;
    }

    /**
     * Divide the given string to paragraphs with the given font and width.
     * 
     * @param strSource
     *            the source string
     * @param font
     *            the font
     * @param width
     *            the width of each line.
     * @return the String array
     */
    static String[] getParagraph(final String strSource, final Paint font, final int width, final String splitChars) {
        String[] strs = null;
        if (strSource == null || font == null || width <= 0) {
            return strs;
        } else if (strSource.equals("")) {
            strs = new String[] { "" };
            return strs;
        }
        Vector<String> vector = new Vector<String>();
        try {
            String temp = strSource;
            int i, j;
            boolean isOver;
            while (!temp.equals("")) {
                isOver = false;
                i = temp.indexOf("\n");
                if (i == -1) {
                    i = temp.length();
                    isOver = font.measureText(temp) > width;
                }
                if (i > 0 && font.measureText(temp.substring(0, i)) > width) {
                    isOver = true;
                }
                if (isOver) {
                    // gets the critical point
                    while (font.measureText(temp.substring(0, i)) > width) {
                        i = i - 1;
                    }
                    if (!splitChars.equals("")) {
                        j = i; // restore the last index of this line for maybe
                        // there is a long word over a line.
                        while (splitChars.indexOf(temp.charAt(i - 1)) == -1) {
                            i--;
                            if (i == 0) {
                                i = j; // crash a word, if it is needed.
                                break;
                            }
                        }
                    }
                }
                vector.addElement(temp.substring(0, i));
                if (i == temp.length()) {
                    temp = "";
                } else {
                    if (temp.charAt(i) == '\n') {
                        temp = temp.substring(i + 1);
                    } else {
                        temp = temp.substring(i);
                    }
                }
            }
            if (vector.size() > 0) {
                strs = new String[vector.size()];
                vector.copyInto(strs);
            }
        } catch (Exception e) {

            printOutToConsole("getSubsection:" + e);
        }
        return strs;
    }


    /**
     * @param src
     *            source image.
     * @param desW
     *            expected width
     * @param keepScale
     *            keeps the scale of the width and height
     * @param isBackgroundTrans
     *            makes the background transparent
     * @param isTrans
     *            makes the image transparent
     * @return Image
     */
    public static final Bitmap scaleImage(Bitmap src, int desW, boolean keepScale, boolean isBackgroundTrans,
            boolean isTrans) {
        Bitmap destImg = null;
        try {
            int desH = src.getHeight();
            if (keepScale) {
                desH = desH * desW / src.getWidth();
            }
            Matrix matrix = new Matrix();
            float scaleWidth = desW;
            float scaleHeight = desH;
            matrix.postScale(scaleWidth, scaleHeight);
            destImg = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true);
        } catch (Exception ex) {

            Utils.printException(ex);
            destImg = null;
        }
        return destImg;
    }

    /**
     * @param src
     *            source image.
     * @param keepScale
     *            keeps the scale of the width and height
     * @param desH
     *            expected height
     * @param isBackgroundTrans
     *            makes the background transparent
     * @param isTrans
     *            makes the image transparent
     * @return Image
     */
    public static final Bitmap scaleImage(Bitmap src, boolean keepScale, int desH, boolean isBackgroundTrans,
            boolean isTrans) {
        Bitmap destImg = null;
        try {
            int desW = src.getWidth();
            if (keepScale) {
                desW = desW * desH / src.getHeight();
            }
            Matrix matrix = new Matrix();
            float scaleWidth = desW;
            float scaleHeight = desH;
            matrix.postScale(scaleWidth, scaleHeight);
            destImg = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true);
        } catch (Exception ex) {

            Utils.printException(ex);
            destImg = null;
        }
        return destImg;
    }

    public static String[] string2Array(String strSrc, String strSepr) {
        String[] astr = null;
        try {
            Vector<String> vec = new Vector<String>(5, 1);
            str2Arr(strSrc, strSepr, vec);
            vec.trimToSize();
            astr = new String[vec.size()];
            vec.copyInto(astr);
            vec.removeAllElements();
        } catch (Exception ex) {
        }
        return astr;
    }

    private static void str2Arr(String strSrc, String strSepr, Vector<String> vec) throws Exception {
        if (strSrc.indexOf(strSepr) == -1) {
            vec.addElement(strSrc);
        } else {
            vec.addElement(strSrc.substring(0, strSrc.indexOf(strSepr)));
            strSrc = strSrc.substring(strSrc.indexOf(strSepr) + strSepr.length());
            str2Arr(strSrc, strSepr, vec);
        }
    }

    private static int[] ori_rgb = null;
    private static int[] dst_rgb = null;
    
    public static Bitmap makeButton(Bitmap imgOri, int width) {
        int ori_w = imgOri.getWidth();
        int ori_h = imgOri.getHeight();
        ori_rgb = new int[ori_w * ori_h];
        dst_rgb = new int[width * ori_h];

        int dst = 0;
        int src = 0;
        imgOri.getPixels(ori_rgb, 0, ori_w, 0, 0, ori_w, ori_h);

        int middle = width - ori_w;
        // Copy the first 6 columns from the ori image to the left border.
        for (int i = 0; i < ori_h; ++i) {
            if (i > 0) {
                src = i * ori_w;
            }
            for (int j = 0; j < ori_w; ++j) {
                dst_rgb[dst++] = ori_rgb[src++];
            }
            src -= 1;
            // Copy background from the 6-th column of the source image.
            for (int j = ori_w; j < middle; ++j) {
                dst_rgb[dst++] = ori_rgb[src];
            }
            // Copy the reverse of ori image to the right border.
            for (int j = middle; j < width; ++j) {
                dst_rgb[dst++] = ori_rgb[src--];
            }
        }
        Bitmap imgDst = Bitmap.createBitmap(dst_rgb, width, ori_h, Bitmap.Config.ARGB_4444);
        ori_rgb = null;
        dst_rgb = null;
        return imgDst;
    }


    // 将传入的字符串中的特殊字符予以替换，保证解析顺利进行或使已替换的字符串还原
    public static String insteadOfSpecillCharacter(String str, boolean isReplace) {
        if ((null == str) || (str.equalsIgnoreCase("")))
            return str;
        String strTemp = str;
        // 特殊字符集
        String[] A = { "&" };
        // 需要替换的字符
        String[] substitute;
        // 替换后的字符集
        String[] B = { "***###" };
        // 替换后的字符
        String[] beReplaced;

        if (isReplace) {
            // 替换特殊字符串，方便解析
            substitute = A;
            beReplaced = B;
        } else {
            // 将特殊字符还原
            substitute = B;
            beReplaced = A;
        }
        int length = substitute.length;
        for (int i = 0; i < length; i++) {
            strTemp = strTemp.replace(substitute[i], beReplaced[i]);
        }
        return strTemp.trim();
    }

    // 将框架元素添加到界面上，并且设置中层框架控件排列方式为置顶
    static public void addManagerAndSetTop(final BaseView bv) {

        // TODO Auto-generated method stub
        bv.runOnUiThread(new Runnable() {

            public void run() {
                // TODO Auto-generated method stub
                bv.show(bv);
                bv.tabBar_.setGravity(Gravity.TOP);
                bv.tabBar_.setContentLayoutGravity();
                WaitDialog.Task.cancelProgressBar(bv);
                isbackcompleted_ = true;
                
                if (bv instanceof LoginView){
                	if (bv.isShouye_){
                		((LoginView) bv).addTitleBar();
                		bv.setBackgroundResource(R.drawable.background, bv, 2);
                	}
                } 
            }
        });
    }

    protected static void checkIsHideTabBar(final BaseView bv) {
        // TODO Auto-generated method stub
        // 当该域获的焦点后执行该方法
        // 如果tab可见，则点击输入框后将其隐藏。
        bv.runOnUiThread(new Runnable() {

            public void run() {
                // TODO Auto-generated method stub
                Object o = bv.tabBar_.llH_.getChildAt(0);
                if ((null != o) && (o instanceof TabItem)) {
                    TabItem tabItem = (TabItem) o;
                    if (tabItem.isShown()) {
                        tabItem.setVisibility(View.GONE);
                        // ((ImageView)
                        // bv.tabBar_.llH_.getChildAt(bv.tabBar_.llH_
                        // .getChildCount() - 1))
                        // .setImageResource(R.drawable.show_btn);
                    }
                }
                if (null != bv.statusBar_)
                    bv.statusBar_.setVisibility(View.GONE);
            }

        });

    }

    // 设置默认的TabBar选项
    static public void initTabBarIndex(BaseView bv) {
        int size = bv.tabBar_.llH_.getChildCount();
        if (size != 0) {
            View view;
            // 保证当前只有一个tab获得焦点且为被选中状态
            for (int i = 0; i < size; i++) {
                view = bv.tabBar_.llH_.getChildAt(i);
                if (i == TabItem.currentTab_) {
                    view.setSelected(true);
                    view.requestFocus();
                } else {
                    view.setSelected(false);
                    view.clearFocus();
                }
            }
        }
    }

    // 设置与是否获得焦点
    static public void setFocus(boolean isFocus, int keyCode, View view) {
        if (view instanceof Table) {
//            Table temp = (Table) view;
            // temp.setFocus(isFocus, keyCode);
        } else {
            if (isFocus) {
                view.requestFocus();
            } else {
                view.clearFocus();
            }
        }

    }

    public static View addArrToTable(BaseView activity) {
        // TODO Auto-generated method stub
        ImageItem imgItem = new ImageItem(activity, Constant.TABLEARR);
        return imgItem;
    }

    /**
     * 检查界面的第一个控件是否带有top=0的属性，如果有则隐藏tabbar
     * 
     * @param bv
     */
    protected static void isHideTabBar(BaseView bv) {
        // TODO Auto-generated method stub
        View view = (View) bv.tabBar_.getContentChild(0);
        if (view instanceof FormLayout) {
            FormLayout temp = (FormLayout) view;
            view = temp.getChildAt(0);
            isHideTabBarThisTime(view, bv);
        } else if (view instanceof Div) {
            Div temp = (Div) view;
            view = temp.getChildAt(0);
            isHideTabBarThisTime(view, bv);
        } else if (view instanceof RowPanel) {
            RowPanel temp = (RowPanel) view;
            view = temp.getChildAt(0);
            isHideTabBarThisTime(view, bv);
        } else if (view instanceof Table) {
            isHideTabBarThisTime(view, bv);
        } else if (view instanceof SegmentLinearLayout) {
            SegmentLinearLayout temp = (SegmentLinearLayout) view;
            view = temp.getChildAt(0);
            isHideTabBarThisTime(view, bv);
        }

    }

    private static void isHideTabBarThisTime(View view, BaseView bv) {
        // TODO Auto-generated method stub
        if (view instanceof mButton) {
            mButton temp = (mButton) view;
            if ((null != temp.cssStyle_) && (temp.cssStyle_.top_ == 0)) {
                hideTabBar(bv, true);
            } else {
                hideTabBar(bv, false);
            }
        } else if (view instanceof cCheckBox) {
            cCheckBox temp = (cCheckBox) view;
            if ((null != temp.cssStyle_) && (temp.cssStyle_.top_ == 0)) {
                hideTabBar(bv, true);
            } else {
                hideTabBar(bv, false);
            }
        }  else if (view instanceof mHtmlText) {
            mHtmlText temp = (mHtmlText) view;
            if ((null != temp.cssStyle_) && (temp.cssStyle_.top_ == 0)) {
                hideTabBar(bv, true);
            } else {
                hideTabBar(bv, false);
            }
        } else if (view instanceof ImageItem) {
            ImageItem temp = (ImageItem) view;
            if ((null != temp.cssStyle_) && (temp.cssStyle_.top_ == 0)) {
                hideTabBar(bv, true);
            } else {
                hideTabBar(bv, false);
            }
        } else if (view instanceof Label) {
            Label temp = (Label) view;
            if ((null != temp.cssStyle_) && (temp.cssStyle_.top_ == 0)) {
                hideTabBar(bv, true);
            } else {
                hideTabBar(bv, false);
            }
        } else if (view instanceof Radio) {
            Radio temp = (Radio) view;
            if ((null != temp.cssStyle_) && (temp.cssStyle_.top_ == 0)) {
                hideTabBar(bv, true);
            } else {
                hideTabBar(bv, false);
            }
        } else if (view instanceof Select) {
            Select temp = (Select) view;
            if ((null != temp.cssStyle_) && (temp.cssStyle_.top_ == 0)) {
                hideTabBar(bv, true);
            } else {
                hideTabBar(bv, false);
            }
        } else if (view instanceof mTextField) {
            mTextField temp = (mTextField) view;
            if ((null != temp.cssStyle_) && (temp.cssStyle_.top_ == 0)) {
                hideTabBar(bv, true);
            } else {
                hideTabBar(bv, false);
            }
        } else if (view instanceof Table) {
            Table temp = (Table) view;
            if ((null != temp.cssStyle_) && (temp.cssStyle_.top_ == 0)) {
                hideTabBar(bv, true);
            } else {
                hideTabBar(bv, false);
            }
        }
    }

    static void hideTabBar(final BaseView bv, final boolean isHide) {
        // TODO Auto-generated method stub
        bv.runOnUiThread(new Runnable() {

            public void run() {
                // TODO Auto-generated method stub
                int size = bv.tabBar_.llH_.getChildCount();
                View view = null;
                int visibility = View.GONE;
                if (!isHide)
                    visibility = View.VISIBLE;
                for (int i = 0; i < size; i++) {
                    view = bv.tabBar_.llH_.getChildAt(i);
                    if (view instanceof ImageView)
                        view.setVisibility(visibility);
                }
            }

        });

    }

    /**
     * @param obj
     */
    public static void printOutToConsole(Object obj) {
        // #ifdef DEBUG
//@        if (obj instanceof String) {
//@            printOutToConsole((String) obj);
//@        } else if (obj instanceof byte[]) {
//@            printOutToConsole((byte[]) obj);
//@        } else {
//@            System.out.println(obj);
//@        }
        // #endif
    }

    public static void printOutToConsole(String s) {
        int length = s.length();
		int pl = 100;
		if (length > pl) {// 解决报文过长，打印不全的问题！
			for (int i = 0; i < length; i += pl) {
				if (i + pl < length) {
					System.out.println(s.substring(i, i + pl));
				} else {
					System.out.println(s.substring(i, length));
				}

			}
		} else {
			System.out.println(s);
		}
        // #ifdef DEBUG
//@//        int length = s.length();
//@//        int pl = 100;
//@//        if (length > pl) {// 解决报文过长，打印不全的问题！
//@//            for (int i = 0; i < length; i += pl) {
//@//            	if (i + pl < length){
//@//            		System.out.println(s.substring(i, i + pl));
//@//            	} else {
//@//            		System.out.println(s.substring(i, length));
//@//            	}
//@//                
//@//            }
//@//        } else {
//@//        	System.out.println(s);
//@//        }
        // #endif
    }

    static void LogD(String tag, String msg) {
        // #ifdef DEBUG
//@        Log.d(tag, msg);
        // #endif
    }
    
    public static void LogE(String tag, String msg) {
        // #ifdef DEBUG
//@        Log.e(tag, msg);
        // #endif
    }

    public static void printException(Exception e) {
        // #ifdef DEBUG
//@        e.printStackTrace();
        // #endif
    	e.printStackTrace();
    }

    public static void isAtTheBottom(BaseView activity) {
        // TODO Auto-generated method stub
        View view = (View) activity.tabBar_.getContentChild(activity.tabBar_.getContentChildCount() - 1);
        if (view instanceof SelfLayout) {
            SelfLayout sl = (SelfLayout) view;
            int lastId = sl.getChildCount() - 1;
            Div lll = (Div) sl.getChildAt(lastId);
            CssStyle cs = lll.getCssStyle();
            if (null != cs) {
                int bottom = cs.bottom_;
                if (bottom != Integer.MIN_VALUE) {
                    LinearLayout.LayoutParams ll = (LayoutParams) activity.tabBar_.scrollDown_.getLayoutParams();
                    ll.bottomMargin = 0;
                }
            }
        } else {
            LinearLayout.LayoutParams ll = (LayoutParams) activity.tabBar_.scrollDown_.getLayoutParams();
            ll.bottomMargin = 10;
        }
    }

    // 从String中得到key和value值
    public static Hashtable<String, String> getFormActionKeyValue(Hashtable<String, String> table, String str) {

        String tmpkey = null;
        String tmpValue = null;

        while (str.indexOf("&") != -1) {
            int idx = str.indexOf("&");
            String keyValue = str.substring(0, idx);// 键值对
            int index = keyValue.indexOf("=");
            tmpkey = keyValue.substring(0, index);
            tmpValue = keyValue.substring(index + 1);
            // System.out.println("tmpkey:"+tmpkey);
            // System.out.println("tmpValue:"+tmpValue);
            table.put(tmpkey, tmpValue);
            str = str.substring(str.indexOf("&") + 1);
        }

        return table;
    }

    /**
     * 
     * 
     * @param hidden
     *            应替换的字符串
     * @param hiddenValue
     *            应填充的字符串
     * @return
     */
    public static String replaceString(String hidden, String hiddenValue) {
        Hashtable<String, String> tbHidden = new Hashtable<String, String>();
        Hashtable<String, String> tbHiddenValue = new Hashtable<String, String>();

        String tmpHidden = hidden;
        String tmpHiddenValue = hiddenValue;

        tbHidden = getFormActionKeyValue(tbHidden, tmpHidden);// 原来hidden中的key
        // value值
        tbHiddenValue = getFormActionKeyValue(tbHiddenValue, tmpHiddenValue);// 新增的key
        // value值

        Enumeration<String> emHiddenKey = null;// 拿出hiddenValue中的所有key
        Enumeration<String> emHiddenValueKey = tbHiddenValue.keys();// 拿出hiddenValue中的所有key
        while (emHiddenValueKey.hasMoreElements()) {// 删除所有与hiddenValue相同的值
            String key = emHiddenValueKey.nextElement();
            // System.out.println("key:"+key);
            String searchkey = null;
            if (!(key.charAt(key.length() - 1) < 48 || key.charAt(key.length() - 1) > 57)) {// key的最后一位是数字
                searchkey = key.substring(0, key.length() - 1);// 去除最后一位数字
            } else {
                searchkey = key;
            }
            // 再做一次去除，保证两位的数字都去掉
            if (searchkey.length() > 1) {
                if (!(searchkey.charAt(searchkey.length() - 1) < 48 || searchkey.charAt(searchkey.length() - 1) > 57)) {// key的最后一位是数字
                    searchkey = searchkey.substring(0, searchkey.length() - 1);// 去除最后一位数字
                }
            }
            // System.out.println("searchkey:"+searchkey);
            emHiddenKey = tbHidden.keys();
            while (emHiddenKey.hasMoreElements()) {
                String hiddenKey = emHiddenKey.nextElement();
                if (hiddenKey.startsWith(searchkey)) {// 找到了相同的key,删除掉
                    tbHidden.remove(hiddenKey);
                }
            }
        }
        // 生成最后需要的字符串
        String result = "";
        emHiddenKey = tbHidden.keys();
        while (emHiddenKey.hasMoreElements()) {
            String key = emHiddenKey.nextElement();
            String value = tbHidden.get(key);
            result += key + "=" + value + "&";
        }
        tmpHiddenValue.concat(result);
        result = tmpHiddenValue + result;
        return result;
    }

    public static String getHidden(String hidden, String name, String value) {
        // TODO Auto-generated method stub
        if (hidden == null) {
            hidden = "";
        }
        if (name != null && value != null) {
            // The last '&' will be remove when do post.
            hidden += name + "=" + Utils.escapeURIComponent(value) + "&";
        }
        return hidden;
    }

    //
    public static String getWeiboHiddenValue(String hidden, String name, String value) {
        // TODO Auto-generated method stub
        if (hidden == null) {
            hidden = "";
        }
        if (name != null && value != null) {
            hidden += name + "=" + value + "&";
        }
        return hidden;
    }
    
    
    public static void releaseResource(View view) {
        if (view instanceof LinearLayout) {
            LinearLayout ll = (LinearLayout) view;
            final int size = ll.getChildCount();
            for (int i = 0; i < size; i++) {
                View v = ll.getChildAt(i);
                if (!(v instanceof Component))
                    break;
                Component c = (Component) v;
                c.releaseResource((View) c);
                c = null;
            }
        } else if (view instanceof RelativeLayout) {
            RelativeLayout rl = (RelativeLayout) view;
            final int size = rl.getChildCount();
            for (int i = 0; i < size; i++) {
                Component c = (Component) rl.getChildAt(i);
                c.releaseResource((View) c);
                c = null;
            }
        }
    }


    /**
     * @param srcBitmap
     *            缩放原图
     * @param desW
     *            需要拉伸的宽度
     * @param dexH
     *            需要拉伸的高度
     * @param mode
     *            缩放模式 0 表示 拉伸处理，不保持纵横比 1 表示按照desW，dexH大的一个去缩放，保持纵横比
     * */
    public static Bitmap scaleImage(BaseView bv, int resourceId, int desW_, int dexH_, int mode_) {
    	releaseBitmap();
        bitmap_ = BitmapFactory.decodeResource(bv.getResources(), resourceId);
        float srcWidth = (float) bitmap_.getWidth();
        float srcHeight = (float) bitmap_.getHeight();
        float desW = (float) desW_;
        float dexH = (float) dexH_;
        
        Matrix matrix = new Matrix();
        
        try {
            if (mode_ == 0) {// 拉伸 不保持纵横比
                matrix.postScale(desW / srcWidth, dexH / srcHeight);
            } else if (mode_ == 1) {// 缩放 保持纵横比
                matrix.postScale(Math.max(desW / srcWidth, dexH / srcHeight), Math.max(desW / srcWidth, dexH
                        / srcHeight));
            }
            if (srcWidth > 0 && srcHeight > 0)
            	bitmap_ = Bitmap.createBitmap(bitmap_, 0, 0, (int)srcWidth, (int)srcHeight,
                        matrix, true);

        } catch (Exception e) {
            Utils.printException(e);
            return bitmap_;
        }
        return bitmap_;
    }


    /**
     * @param byts
     */
    public static void printOutToConsole(byte[] byts) {
        // #ifdef DEBUG
//@        if (byts == null) {
//@            return;
//@        }
//@        for (int i = 0; i < byts.length; i++) {
//@            System.out.print("[" + i + "]" + " : \t");
//@            System.out.println(byts[i]);
//@        }
        // #endif
    }

    /**
     * Network Byte Order
     * 
     * @param intValue
     * @return
     */
    public static byte[] intToByteArrayInNBO(int intValue) {
        byte[] byt = new byte[4];
        for (int i = 0; i < 4; i++) {
            byt[i] = (byte) (intValue >>> (24 - i * 8));
        }
        return byt;
    }

    /**
     * Network Byte Order
     * 
     * @param byts
     * @param offset
     * @return
     */
    public static int byteArrayToIntInNBO(byte[] byts, int offset) {
        int intValue = 0;
        for (int i = 0; i < 4; i++) {
            int shift = (4 - 1 - i) * 8;
            intValue += (byts[i + offset] & 0x000000FF) << shift;
        }
        return intValue;
    }

    /**
     * 在主界面显示预留信息提示框
     * 
     * @param mid
     * @param bv
     */
    public static void showLoginMessage(Mid mid, BaseView bv) {
        // TODO Auto-generated method stub
    	if (mid.um_.loginStatus_.equals("1")) userIsNotFirstLogin_ = true;
    	
        String title;
        final String lastTime = mid.um_.lastLogin_;
        String preInfo;
        try {
        	title = URLDecoder.decode(mid.um_.name_);
        } catch (IllegalArgumentException e) {
        	title = mid.um_.name_;
        }
        try {
        	preInfo = URLDecoder.decode(mid.um_.checkInfo_);
        } catch (IllegalArgumentException e) {
        	preInfo = mid.um_.checkInfo_;
        }
        mid.alert(bv, title.concat("\n").concat(lastTime).concat("\n").concat(preInfo), false);
        
    }

    /**
     * 将存储的控件存储属性转换成hashmap的形式
     * 
     * @param save
     * @return
     */
    public static HashMap<String, Object> getSavePropoerty(String save) {
        if (null == save)
            return null;
        // TODO Auto-generated method stub
        HashMap<String, Object> hm = new HashMap<String, Object>();
        String name = "";
        String value = "";
        String remain = save;
        while (remain.indexOf(ConfigManager.SAVENEND) != -1) {
            int nIndex = remain.indexOf(ConfigManager.SAVENEND);

            if (nIndex != -1) {
                // 把值的获取放在名获取里面保证名值的匹配
                name = remain.substring(0, nIndex + ConfigManager.SAVENEND.length());
                name = name.substring(0, nIndex);
                remain = remain.substring(nIndex + ConfigManager.SAVENEND.length());
                int vIndex = remain.indexOf(ConfigManager.SAVEVEND);
                if (vIndex != -1) {
                    value = remain.substring(0, vIndex + ConfigManager.SAVEVEND.length());
                    value = value.substring(0, vIndex);
                    remain = remain.substring(vIndex + ConfigManager.SAVEVEND.length());
                }
                hm.put(name, value);
            }
        }
        return hm;
    }

    /**
     * 存储控件save属性
     * 
     * @param bv
     * @param itemV
     */
//	public static void saveProperties(BaseView bv, String str) {
//		
//		 bv.mid_.pm_.SAVEPROPERTYDB_.savephonenum("loginfo", str);
//	}
    public static void saveProperties(BaseView bv, Vector<Component> itemV) {
        // TODO Auto-generated method stub
        final int sz = itemV.size();
        Object o;
        View attItem;
//        View temp;
        // 先对带reitem属性的单选控件做一次校正，再把整个hash转换成键值对形势进行存储
        for (int i = 0; i < sz; i++) {
            o = itemV.elementAt(i);
            if (o instanceof Wrap)
                continue;
            else
                attItem = (View) o;
            
			if (!attItem.isShown()) {
				continue;
			}
            
            if (attItem instanceof SegmentLinearLayout) {
                SegmentLinearLayout sll = (SegmentLinearLayout) attItem;
                final int sizeSll = sll.getChildCount();
                for (int j = 0; j < sizeSll; j++) {
                    searchSavePropertyWithRadio(bv, (Radio) sll.getChildAt(j), itemV);
                }
            } else if (attItem instanceof Radio) {
                Radio radio = (Radio) attItem;
                searchSavePropertyWithRadio(bv, radio, itemV);
            } else if (attItem instanceof Select) {
            	searchSavePropertyWithTrueSave(bv, (Select) attItem);
            } else if (attItem instanceof mTextField) {
            	mTextField ltf = (mTextField) attItem;
            	searchSavePropertyWithTrueSave(bv, ltf);
            }
        }
        
        saveProperties ();
    }
    
    public static void saveProperties () {
    	// 遍历哈西map，将其内容转化成字符串进行存储
        if (Mid.saveProperty_.size() > 0) {
            Iterator<Entry<String, Object>> iter = Mid.saveProperty_.entrySet().iterator();
            Map.Entry<String, Object> enter;
            String key, value;
            StringBuffer sb = new StringBuffer();
            if (null != iter) {
                while (iter.hasNext()) {
                    // 将存储字符串按一定规则拼起
                    enter = (Entry<String, Object>) iter.next();
                    key = enter.getKey().toString();
                    value = enter.getValue().toString();
                    if (!key.equals("") && !value.equals("")) {
                        sb.append(key);
                        sb.append(ConfigManager.SAVENEND);
                        sb.append(value);
                        sb.append(ConfigManager.SAVEVEND);
                    }
                }
                BaseView.mid_.pm_.SAVEPROPERTYDB_.save(PackageManagerAndroid.SAVEPROPERTY_DB, sb.toString());
            }
        } else {
        	BaseView.mid_.pm_.SAVEPROPERTYDB_.save(PackageManagerAndroid.SAVEPROPERTY_DB, "");
        }
    }
    
    
	private static void searchSavePropertyWithTrueSave(BaseView bv, Select selct) {
		FormAction faction = bv.getFormByComponent(selct);
		if (null != Mid.saveProperty_ && null != faction.name_ && null != faction.action_ && null != selct.attrName_) {
			String key;
			if (selct.tableName_ != null){
				key = faction.action_.concat(selct.tableName_).concat(selct.attrName_);
			} else {
				key = faction.action_.concat(selct.attrName_);
			}
			String value = ((Select.Option) selct.dropdownMenuText_.elementAt(selct.currentMenu_)).label_;
			if (selct.attrTrueSave_) {
				Mid.saveProperty_.put(key, value);
			}
		}
	}

	private static void searchSavePropertyWithTrueSave(BaseView bv, mTextField textField) {
		if (!(textField.saveHistory_ || textField.attrTrueSave_)) {//如果两个属性都为假，则返回，不执行存储操作
			return;
		}
		FormAction faction = bv.getFormByComponent(textField);
		if (null != Mid.saveProperty_ && null != faction.name_ && null != faction.action_ && null != textField.attrName_) {
			String key ; 
			String value ;
			if (textField.tableName_ != null){
				key = faction.name_.concat(faction.action_).concat(textField.tableName_).concat(textField.attrName_);
			} else {
				key = faction.name_.concat(faction.action_).concat(textField.attrName_);
			}
			if((textField.mask_)&&(textField.attrTrueValue_!=null)){
				value = textField.attrTrueValue_;
			} else {
				value = textField.getContentText();
			}
			if (textField.saveHistory_) {
				String phoneStr = (String) Mid.saveProperty_.get(key);
				if (value.equals("")){
					return;
				} else {
					value = value.concat("#");
				}
				if (phoneStr != null && phoneStr.trim() != "") {
					if (phoneStr.contains(value)) {
						phoneStr = phoneStr.replace(value, "");
						value = value.concat(phoneStr);
					} else {
						value = value.concat(phoneStr);
					}
				}
			} 

			Mid.saveProperty_.put(key, value);
		}
	}
	
    /**
     * 根据radio的相关属性编辑存储哈希表内容
     * 
     * @param bv
     * @param radio
     * @param itemV
     */
    private static void searchSavePropertyWithRadio(BaseView bv, Radio radio, Vector<Component> itemV) {
        // TODO Auto-generated method stub
        final int sz = itemV.size();
        Object o;
//        View attItem;
        View temp;
        if (null != radio.attrReitem && radio.isChecked()) {
			// 如果控件存在该属性则需对存储进行一次校正
			for (int j = 0; j < sz; j++) {
				o = itemV.elementAt(j);
				if (o instanceof Wrap)
					continue;
				temp = (View) o;

				if (temp instanceof mTextField) {
					mTextField texfield = (mTextField) temp;
					if (texfield.getTag().toString().contains(radio.attrReitem)) {
						// 查找与radio相对应的控件
						FormAction faction = bv.getFormByComponent(texfield);
						if (radio.attrValue_.equalsIgnoreCase("yes")) {
							// 作增加操作
							// 如果xml报文显示save为yes，则将该页面的form名称和url以及下拉框控件名称组成一个键名。键值用选中的option对象
							if (null != Mid.saveProperty_&& null != faction.name_&& null != faction.action_&& null != texfield.attrName_) {
								String key = faction.name_.concat(faction.action_).concat(texfield.attrName_);
//								String value = texfield.getContentText().trim();
								String value ;
								if((texfield.mask_)&&(texfield.attrTrueValue_!=null)){
									value = texfield.attrTrueValue_;
								} else {
									value = texfield.getContentText();
								}
								if (texfield.saveHistory_) {
									String phoneStr = (String) Mid.saveProperty_.get(key);
									value = value.concat("#");
									if (phoneStr != null&& phoneStr.trim() != "") {
										if (phoneStr.contains(value)) {
											phoneStr=phoneStr.replace(value,"");
											value = value.concat(phoneStr);
										}else{
										value = value.concat(phoneStr);
										}
									}
								}
								Mid.saveProperty_.put(key, value);
							}
						} else {
							// 作删除操作
							if (null != Mid.saveProperty_
									&& null != faction.name_
									&& null != faction.action_
									&& null != texfield.attrName_) {

								String key = faction.name_.concat(faction.action_).concat(texfield.attrName_);
//								String value = texfield.getContentText().trim();
								String value ;
								if((texfield.mask_)&&(texfield.attrTrueValue_!=null)){
									value = texfield.attrTrueValue_;
								} else {
									value = texfield.getContentText();
								}
								String phoneStr = (String) Mid.saveProperty_.get(key);
								value = value.concat("#");	
								if (texfield.saveHistory_ && phoneStr != null && phoneStr.trim() != "") {
									if (phoneStr.contains(value)) {
										phoneStr=phoneStr.replace(value,"");
										if (phoneStr == "") {
											Mid.saveProperty_.remove(key);
										} else {
											value=phoneStr;
											Mid.saveProperty_.put(key, value);
										}
									}
								} else if (Mid.saveProperty_.containsKey(key)) {
									Mid.saveProperty_.remove(key);
								}
								
							}
						}
						break;
					}
				}
			}
		}
    }

    public static int getScaledValue(float num) {
        // TODO Auto-generated method stub
        if (SCALEDATE_W != 1 || DM_DENSITY != 1) {
            num = (int) (SCALEDATE_W * num * DM_DENSITY);
        }
        return (int)(num + 1);
    }
    public static int getSystemScaledValue(int num) {
        // TODO Auto-generated method stub
        if (DM_DENSITY != 1) {
            num = (int) (DM_DENSITY * num);
        }
        return num;
    }
    public static int getUserDeviceScaledValue(float num) {
        // TODO Auto-generated method stub
        if (SCALEDATE_W != 1) {
            num = SCALEDATE_W * num;
        }
        return (int)(num + 1);
    }

    private static void releaseBitmap () {
    	if (bitmap_ != null) {
    		if (bitmap_.isRecycled()) {
    			Utils.printOutToConsole("bitmap_ has been recycled!!");
    		}
    		bitmap_ = null;
    	}
    }
    
    public static Bitmap getScaledBitmap(Resources rs, int resId, Options opts) {
        // TODO Auto-generated method stub
    	releaseBitmap ();
        bitmap_ = BitmapFactory.decodeResource(rs, resId, opts);
//        if (SCALEDATE_W != 0 || SCALEDATE_H != 0) {
//            bitmap_ = Bitmap.createScaledBitmap(bitmap_, (int) (bitmap_.getWidth() * SCALEDATE_W),
//                    (int) (bitmap_.getHeight() * SCALEDATE_H), true);
//        }
        return bitmap_;
    }

    public static Bitmap getScaledBitmap(Resources rs, int resId) {
        // TODO Auto-generated method stub
    	releaseBitmap ();
    	if (resId != 99){
    		bitmap_ = BitmapFactory.decodeResource(rs, resId);
    	}
        if (SCALEDATE_W != 1 || SCALEDATE_H != 1) {
        	bitmap_ = Bitmap.createScaledBitmap(bitmap_, (int) (bitmap_.getWidth() * SCALEDATE_W),
                    (int) (bitmap_.getHeight() * SCALEDATE_H), true);
        }
        return bitmap_;
    }

	/**
	 * 添加倒影，原理，先翻转图片，由上到下放大透明度
	 * 
	 * @param originalImage
	 * @return
	 */
	public static Bitmap createReflectedImage(Bitmap originalImage) {
		// The gap we want between the reflection and the original image
		final int reflectionGap = 4;

		int width = originalImage.getWidth();
		int height = originalImage.getHeight();

		// This will not scale but will flip on the Y axis
		Matrix matrix = new Matrix();
		matrix.preScale(1, -1);

		// Create a Bitmap with the flip matrix applied to it.
		// We only want the bottom half of the image
		Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
				height / 4, width, height / 4, matrix, false);

		// Create a new bitmap with same width but taller to fit reflection
		Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
				(height + height / 4), Config.ARGB_8888);

		// Create a new Canvas with the bitmap that's big enough for
		// the image plus gap plus reflection
		Canvas canvas = new Canvas(bitmapWithReflection);
		// Draw in the original image
		canvas.drawBitmap(originalImage, 0, 0, null);
		// Draw in the gap
		Paint defaultPaint = new Paint();
		canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
		// Draw in the reflection
		canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);

		// Create a shader that is a linear gradient that covers the reflection
		Paint paint = new Paint();
		LinearGradient shader = new LinearGradient(0,
				originalImage.getHeight(), 0, bitmapWithReflection.getHeight()
						+ reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
		// Set the paint to use this shader (linear gradient)
		paint.setShader(shader);
		// Set the Transfer mode to be porter duff and destination in
		paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
		// Draw a rectangle using the paint with our linear gradient
		canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
				+ reflectionGap, paint);

		return bitmapWithReflection;
	}

	//drawable 类型转化为bitmap
	public static Bitmap drawableToBitmap(Drawable drawable) {

		Bitmap bitmap = Bitmap
				.createBitmap(
						drawable.getIntrinsicWidth(),
						drawable.getIntrinsicHeight(),
						drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
								: Bitmap.Config.RGB_565);
		Canvas canvas = new Canvas(bitmap);
		// canvas.setBitmap(bitmap);
		drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable
				.getIntrinsicHeight());
		drawable.draw(canvas);
		return bitmap;
	}

    /**
     *  读取指定键值对的值
     *  param key     b
     *  param src     a=111&b=222&c=333&
     * @return value  222
     */ 
	@SuppressWarnings("finally")
	public static String getValueByKey(String key, String src) {
		String value = null;
		try {
			StringTokenizer token = new StringTokenizer(src, "&");
			while (token.hasMoreTokens()) {
				String temp = token.nextToken();
				if (null != temp && temp.indexOf(key) != -1) {
					String spStr[] = temp.split("=");
					value = spStr[1];
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			return value;
		}
	}
	
	/** 
	  * 获取CPU序列号 
	  *  
	  * @return CPU序列号(16位) 
	  * 读取失败为 0000000000000000
	  */  
	public static String getCPUSerial() {
		String str = "", strCPU = "", cpuAddress = "0000000000000000";
		try {
			// 读取CPU信息
			Process pp = Runtime.getRuntime().exec("cat /proc/cpuinfo");
			InputStreamReader ir = new InputStreamReader(pp.getInputStream());
			LineNumberReader input = new LineNumberReader(ir);
			// 查找CPU序列号
			for (int i = 1; i < 100; i++) {
				str = input.readLine();
				if (str != null) {
					// 查找到序列号所在行
					if (str.indexOf("Serial") > -1) {
						// 提取序列号
						strCPU = str.substring(str.indexOf(":") + 1, str.length());
						// 去空格
						cpuAddress = strCPU.trim();
						break;
					}
				} else {
					// 文件结尾
					break;
				}
			}
		} catch (IOException ex) {
			// 赋予默认值
			printException(ex);
		}
		printOutToConsole("cpuSerial = " + cpuAddress);
		return cpuAddress;
	}
	
	/**
	 * 获取图片名称获取图片的资源id的方法
	 * 
	 * @param imageName
	 * @return
	 */
	public static int getResourceByReflect(String imageName) {
		Class<drawable> drawable = R.drawable.class;
		Field field = null;
		int imgId;
		try {
			field = drawable.getDeclaredField(imageName);
			imgId = field.getInt(field.getName());
		} catch (Exception e) {
			imgId = 99;
			Utils.printOutToConsole("ERROR==============PICTURE NOT　FOUND！");
		}
		return imgId;
	}

	/**
	 * 返回指定格式的日期字符串
	 * @param date
	 * @return
	 */
    public static String[] date2String(Date date){
    	String result [] = null;
        try {
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy,MM,dd,HH,mm,ss");       
			String timeString = dateFormat.format(date);
			result = timeString.split(",");
		} catch (Exception e) {
			printOutToConsole(e.getMessage());
		}
		return result;
    }
	
    
	
	/**
	 * 把字符串按每两位切割成数组
	 * @param str
	 * @return
	 */
	public static String[] splitByTwo (String str) {
		String [] result = null;
		if(!TextUtils.isEmpty(str) && str.length() == 34) {
			result = new String[17];
			int i = 0;
			while(str.length() > 0) {
				result[i] = str.substring(0, 2);
				str = str.substring(2);
				i++;
			}
		}
		return result;
	}
	

	/**
	 * 把16进制字符串转换成字节数组
	 * @param hexstr
	 * @return
	 */
	public static byte[] HexString2Bytes(String hexstr) {
		byte[] b = new byte[hexstr.length() / 2];
		int j = 0;
		for (int i = 0; i < b.length; i++) {
			char c0 = hexstr.charAt(j++);
			char c1 = hexstr.charAt(j++);
			b[i] = (byte) ((parse(c0) << 4) | parse(c1));
		}
		return b;
	}

	private static int parse(char c) {
		if (c >= 'a')
			return (c - 'a' + 10) & 0x0f;
		if (c >= 'A')
			return (c - 'A' + 10) & 0x0f;
		return (c - '0') & 0x0f;
	}
    
	/**
	 * 处理数字串，精确到小数点后两位
	 * @param src
	 * @return
	 */
	public static String appendPostFix(String src) {
		StringBuffer sb = new StringBuffer();
		if (null != src && src.trim().length() > 0) {
			if (src.indexOf(".") != -1) {
				String preFix = src.substring(0, src.indexOf(".") + 1);
				String postFix = src.substring(src.indexOf(".") + 1);
				if (!TextUtils.isEmpty(postFix)) {
					sb.append(preFix);
					int len = postFix.length();
					if (len > 2) {
						sb.append(postFix.substring(0, 2));
					} else if (len < 2) {
						sb.append(postFix).append("0");
					} else {
						sb.append(postFix);
					}
				} else {
					sb.append(preFix);
					sb.append("00");
				}
			} else {
				sb.append(src.trim());
				sb.append(".00");
			}
		}
		return sb.toString();
	}

	/**
	 * 把字节数组转换成16进制字符串
	 * @param bArray
	 * @return
	 */
	public static final String bytesToHexString(byte[] bArray) {
	    StringBuffer sb = new StringBuffer(bArray.length);
	    String sTemp;
	    for (int i = 0; i < bArray.length; i++) {
	     sTemp = Integer.toHexString(0xFF & bArray[i]);
	     if (sTemp.length() < 2)
	      sb.append(0);
	     sb.append(sTemp.toUpperCase());
	    }
	    return sb.toString();
	}

	/**
	 * 保存字符到本地
	 * @param str
	 */
	public static void saveFile(String str) {
		String filePath = null;
		boolean hasSDCard = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
		if (hasSDCard) {
			filePath = Environment.getExternalStorageDirectory().toString() + File.separator + "hello.txt";
		} else
			filePath = Environment.getDownloadCacheDirectory().toString() + File.separator + "hello.txt";
		
		try {
			File file = new File(filePath);
			if (!file.exists()) {
				File dir = new File(file.getParent());
				dir.mkdirs();
				file.createNewFile();
			}
			FileOutputStream outStream = new FileOutputStream(file);
			outStream.write(str.getBytes());
			outStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 把asset下的文件转换成字符串
	 * @param activity
	 * @param fileName
	 * @return
	 */
    public final static String getStringFormAsset(Activity activity, String fileName) {
        BufferedReader in = null;
        InputStream ins = null;
        InputStreamReader inr = null;
        try {
            ins = activity.getAssets().open(fileName);
            inr = new InputStreamReader(ins);
            in = new BufferedReader(inr, 8 * 1024);
            String line;
            StringBuilder buffer = new StringBuilder();
            while ((line = in.readLine()) != null)
                buffer.append(line).append('\n');
            return buffer.toString();
        } catch (IOException e) {
            printException(e);
            return "";
        } finally {
            try {
                ins.close();
            } catch (IOException e1) {
            }
            try {
                inr.close();
            } catch (IOException e1) {
            }
            if (in != null) {
                try {
                    in.close();
                    in = null;
                } catch (IOException e) {
                }
            }
        }
    }
    
    
    /**
     * 解读assets文件夹下的Config.txt文件信息
     * 
     * @param activity
     * @param tag
     *            需要在该文件里面查找的key
     * @return 文件中key对应的value
     */
    public final static String getConfigStringFormAsset(Activity activity, String tag) {
        if (configHm_ == null) {
            initConfigStringFormAsset(activity);
        }
        String value = configHm_.get(tag);
        return value == null ? "" : value;
    }

    /**
     * 解读assets文件夹下的Config.txt文件信息
     * 
     * @param activity
     * @param tag
     *            需要在该文件里面查找的key
     * @return 文件中key对应的value
     */
    private final static void initConfigStringFormAsset(Activity activity) {
        // 　只读取一次Config文件
        if (null == activity)
            return;
        configHm_ = new HashMap<String, String>();
        BufferedReader in = null;
        InputStream ins = null;
        InputStreamReader inr = null;
        try {
            ins = activity.getAssets().open("Config.txt");
            inr = new InputStreamReader(ins);
            in = new BufferedReader(inr, 1024);
            String line;
            String key;
            String value;
            while ((line = in.readLine()) != null) {
                int index = line.indexOf(" ");
                if (index != -1) {
                    key = line.substring(0, index);
                    value = line.substring(index).trim();// 去掉前面的空格
                    configHm_.put(key, value);
                }
            }

            String str_lag = configHm_.get("jat_lag");
            jat_lag = Integer.parseInt(str_lag);
        } catch (Exception e) {
        } finally {
            try {
                ins.close();
            } catch (IOException e1) {
            }
            try {
                inr.close();
            } catch (IOException e1) {
            }
            if (in != null) {
                try {
                    in.close();
                    in = null;
                } catch (Exception e) {
                    printException(e);
                }
            }
        }
    }

    /**
     * 拨打电话号码
     * @param activity
     * @param phoneNum
     */
    public static void dialPhone(Activity activity, String phoneNum) {
        //传入服务， parse（）解析号码
        Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phoneNum));
        //通知activtity处理传入的call服务
        activity.startActivity(intent);
    }
    
    // 压缩   
    public static String compress(String str) throws IOException {   
       if (str == null || str.length() == 0) {   
        return str;   
      }   
       ByteArrayOutputStream out = new ByteArrayOutputStream();   
      GZIPOutputStream gzip = new GZIPOutputStream(out);   
       gzip.write(str.getBytes());   
       gzip.close();   
      return out.toString("ISO-8859-1");   
     }   
    
    /**
     * 创建json 
     * @param ls
     * @return
     */
	public static String makeJson(List<ItemBase> ls, String infoType) {
		String mJson = null;
		GsonBuilder gsonBuilder = new GsonBuilder();
		Gson gson = gsonBuilder.create();
		if (null != infoType) {
			if(infoType.equals("1")) {
				Type type = new TypeToken<List<ItemInfo>>(){}.getType();//优惠
				mJson = gson.toJson(ls, type);
			} else if (infoType.equals("3")) {
				Type type = new TypeToken<List<ItemMeal>>(){}.getType();//菜品
				mJson = gson.toJson(ls, type);
			}
		}
		return  mJson;
	}
	
	/**
	 * 解析Json
	 * @param result
	 * @return
	 */
	public static List<ItemBase> parseJson(String result, String infoType){
		List<ItemBase> list = new ArrayList<ItemBase>();
		Gson gson = new Gson();
		if (result != null && infoType != null) {
			Type type = null;
			if (infoType.trim().equals("1")) {
				type = new TypeToken<List<ItemInfo>>() {}.getType();
				list = gson.fromJson(result, type);
			} else if (infoType.trim().equals("2")) {
				type = new TypeToken<List<ItemRestaurant>>() {}.getType();
				list = gson.fromJson(result, type);
			} else if (infoType.trim().equals("3")) {
				type = new TypeToken<List<ItemMeal>>() {}.getType();
				list = gson.fromJson(result, type);
			}
		}
		
		return list;
	}
}
